changeset 4531:3a309467fc8e

Merge
author Christian Haeubl <christian.haeubl@oracle.com>
date Wed, 08 Feb 2012 21:15:00 -0800
parents 6c6cb7be1324 (current diff) 681e969888a7 (diff)
children 6dda62bf5be4
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/Location.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LocationMap.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/ValueUtil.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LIRInsertionBuffer.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/ExceptionInfo.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/TargetMethodAssembler.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Block.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/BlockMap.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/CFGVerifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/ControlFlowGraph.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Loop.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/FrameMap.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIR.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LabelRef.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/Variable.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/CompilationEvent.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/CompilationObserver.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/ObservableContext.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/package-info.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Arithmetic.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Call.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Compare.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompareToIntOpcode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRInstruction.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Move.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64SlowPath.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.properties src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.xml src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/Bundle.properties src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphNode.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.form src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardConfiguration.xml src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/Bundle.properties src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphAction.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphCookie.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphOpenCookie.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphRemoveCookie.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/OutlineAction.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAction.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAllAction.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveCookie.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAllAction.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAsAction.java src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/customLeftWsmode.xml src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/import.png src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/remove.png src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/removeall.png src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/save.png src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/saveall.gif src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/layer.xml src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/build-impl.xml src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/genfiles.properties src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.properties src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.xml src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Bundle.properties src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Client.java src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Server.java src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/project.properties src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.properties src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.xml src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/color.filter src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/onlyControlFlow.filter src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/register.filter src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/remove.filter src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/layer.xml src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ContextAction.java src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/LookupHistory.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/BoundedZoomAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewer.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorInputGraphProvider.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.form src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExportCookie.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedSatelliteComponent.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/GraphViewerImplementation.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/NodeQuickSearch.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/CustomizablePanAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExportAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NextDiagramAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/OverviewAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PanModeAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PrevDiagramAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/SelectionModeAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ShowAllAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomInAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomOutAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/export.png src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/next_diagram.png src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/prev_diagram.png src/share/vm/graal/graalCompilerToVM.cpp
diffstat 651 files changed, 41530 insertions(+), 8486 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Feb 08 21:13:35 2012 -0800
+++ b/.hgignore	Wed Feb 08 21:15:00 2012 -0800
@@ -23,8 +23,8 @@
 \.pdf$
 \.dot$
 \.pyc$
-build.xml
-nbproject
+^graal/.*/build.xml
+^graal/.*/nbproject/
 dist
 ^doc/.*/dot_temp_
 ^doc/doxygen/.*$
@@ -36,6 +36,7 @@
 /nbproject/private/
 ^graal/hotspot/java$
 ^scratch/
+^test-output/
 scratch/
 bin/
 ^local/
@@ -43,5 +44,9 @@
 ^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/
 ^src/share/tools/IdealGraphVisualizer/build/
 ^src/share/tools/IdealGraphVisualizer/dist/
+^visualizer/[a-zA-Z0-9]*/build/
+^visualizer/build/
+^visualizer/dist/
+^visualizer/nbplatform/
 ^.hgtip
 .DS_Store
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/AbstractAssembler.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/AbstractAssembler.java	Wed Feb 08 21:15:00 2012 -0800
@@ -48,6 +48,10 @@
         l.patchInstructions(this);
     }
 
+    public abstract void align(int modulus);
+
+    public abstract void jmp(Label l);
+
     protected abstract void patchJumpTarget(int branch, int jumpTarget);
 
     protected final void emitByte(int x) {
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/NumUtil.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/NumUtil.java	Wed Feb 08 21:15:00 2012 -0800
@@ -98,4 +98,8 @@
         assert isShort(v);
         return (short) v;
     }
+
+    public static int roundUp(int number, int mod) {
+        return ((number + mod - 1) / mod) * mod;
+    }
 }
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java	Wed Feb 08 21:15:00 2012 -0800
@@ -759,6 +759,7 @@
         }
     }
 
+    @Override
     public final void jmp(Label l) {
         if (l.isBound()) {
             jmp(l.position(), false);
@@ -2876,6 +2877,7 @@
         testl(AMD64.rax, new CiAddress(Word, r.asValue(Word), 0));
     }
 
+    @Override
     public void align(int modulus) {
         if (codeBuffer.position() % modulus != 0) {
             nop(modulus - (codeBuffer.position() % modulus));
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiUtil.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiUtil.java	Wed Feb 08 21:15:00 2012 -0800
@@ -728,11 +728,11 @@
         return result;
     }
 
-    public static Class<?>[] signatureToTypes(RiSignature signature, RiType accessingClass) {
+    public static Class<?>[] signatureToTypes(RiSignature signature, RiResolvedType accessingClass) {
         int count = signature.argumentCount(false);
         Class<?>[] result = new Class<?>[count];
         for (int i = 0; i < result.length; ++i) {
-            result[i] = ((RiResolvedType) signature.argumentTypeAt(i, accessingClass)).toJava();
+            result[i] = signature.argumentTypeAt(i, accessingClass).resolve(accessingClass).toJava();
         }
         return result;
     }
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiSignature.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiSignature.java	Wed Feb 08 21:15:00 2012 -0800
@@ -49,7 +49,7 @@
      *        not care for a resolved type.
      * @return the {@code index}'th argument type
      */
-    RiType argumentTypeAt(int index, RiType accessingClass);
+    RiType argumentTypeAt(int index, RiResolvedType accessingClass);
 
     /**
      * Gets the argument kind at the specified position.
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiType.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiType.java	Wed Feb 08 21:15:00 2012 -0800
@@ -97,4 +97,6 @@
      * @return the kind of constants for the specified part of the type
      */
     CiKind getRepresentationKind(Representation r);
+
+    RiResolvedType resolve(RiResolvedType accessingClass);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.alloc.simple;
+
+import static com.oracle.max.graal.alloc.util.LocationUtil.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.alloc.util.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.LIRInstruction.*;
+import com.oracle.max.graal.lir.cfg.*;
+
+public abstract class AssignRegisters {
+    public final LIR lir;
+    public final FrameMap frameMap;
+
+    public AssignRegisters(LIR lir, FrameMap frameMap) {
+        this.lir = lir;
+        this.frameMap = frameMap;
+    }
+
+    private CiBitMap curRegisterRefMap;
+    private CiBitMap curFrameRefMap;
+
+    public void execute() {
+        ValueProcedure useProc =          new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value); } };
+        ValueProcedure defProc =          new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value); } };
+        ValueProcedure setReferenceProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return setReference(value); } };
+
+        Debug.log("==== start assign registers ====");
+        for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) {
+            Block block = lir.linearScanOrder().get(i);
+            Debug.log("start block %s", block);
+
+            curRegisterRefMap = frameMap.initRegisterRefMap();
+            curFrameRefMap = frameMap.initFrameRefMap();
+
+            // Put all values live at the end of the block into the reference map.
+            locationsForBlockEnd(block).forEachLocation(setReferenceProc);
+
+            for (int j = block.lir.size() - 1; j >= 0; j--) {
+                LIRInstruction op = block.lir.get(j);
+                Debug.log("  op %d %s", op.id(), op);
+
+                op.forEachOutput(defProc);
+                op.forEachTemp(defProc);
+                op.forEachState(useProc);
+                op.forEachAlive(useProc);
+
+                if (op.info != null) {
+                    Debug.log("    registerRefMap: %s  frameRefMap: %s", curRegisterRefMap, curFrameRefMap);
+                    op.info.finish(new CiBitMap(curRegisterRefMap), new CiBitMap(curFrameRefMap), frameMap);
+
+                    if (op instanceof LIRXirInstruction) {
+                        LIRXirInstruction xir = (LIRXirInstruction) op;
+                        if (xir.infoAfter != null) {
+                            xir.infoAfter.finish(new CiBitMap(curRegisterRefMap), new CiBitMap(curFrameRefMap), frameMap);
+                        }
+                    }
+                }
+
+                // Process input operands after assigning the reference map, so that input operands that are used
+                // for the last time at this instruction are not part of the reference map.
+                op.forEachInput(useProc);
+            }
+            Debug.log("end block %s", block);
+        }
+        Debug.log("==== end assign registers ====");
+    }
+
+    private CiValue use(CiValue value) {
+        Debug.log("    use %s", value);
+        if (isLocation(value)) {
+            CiValue location = asLocation(value).location;
+            frameMap.setReference(location, curRegisterRefMap, curFrameRefMap);
+            return location;
+        } else {
+            frameMap.setReference(value, curRegisterRefMap, curFrameRefMap);
+            return value;
+        }
+    }
+
+    private CiValue def(CiValue value) {
+        Debug.log("    def %s", value);
+        if (isLocation(value)) {
+            CiValue location = asLocation(value).location;
+            frameMap.clearReference(location, curRegisterRefMap, curFrameRefMap);
+            return location;
+        } else {
+            frameMap.clearReference(value, curRegisterRefMap, curFrameRefMap);
+            return value;
+        }
+    }
+
+    private CiValue setReference(CiValue value) {
+        Debug.log("    setReference %s", value);
+        frameMap.setReference(asLocation(value).location, curRegisterRefMap, curFrameRefMap);
+        return value;
+    }
+
+    protected abstract LocationMap locationsForBlockEnd(Block block);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.alloc.simple;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+import static com.oracle.max.graal.lir.ValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.LIRInstruction.*;
+import com.oracle.max.graal.lir.cfg.*;
+
+public class DataFlowAnalysis {
+    private final LIR lir;
+    private final RiRegisterConfig registerConfig;
+
+    public DataFlowAnalysis(LIR lir, RiRegisterConfig registerConfig) {
+        this.lir = lir;
+        this.registerConfig = registerConfig;
+    }
+
+    public void execute() {
+        numberInstructions();
+        backwardDataFlow();
+    }
+
+
+    private List<Block> blocks() {
+        return lir.linearScanOrder();
+    }
+
+    private int numVariables() {
+        return lir.numVariables();
+    }
+
+    private boolean isAllocatableRegister(CiValue value) {
+        return isRegister(value) && registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
+    }
+
+
+    private int[] definitions;
+    private BitSet[] blockLiveIn;
+    private Block[] opIdBlock;
+    private Object[] opIdKilledValues;
+
+
+    public BitSet liveIn(Block block) {
+        return blockLiveIn[block.getId()];
+    }
+    private void setLiveIn(Block block, BitSet liveIn) {
+        blockLiveIn[block.getId()] = liveIn;
+    }
+
+    private Block blockOf(int opId) {
+        return opIdBlock[opId >> 1];
+    }
+    private void setBlockOf(int opId, Block block) {
+        opIdBlock[opId >> 1] = block;
+    }
+
+    private Object killedValues(int opId) {
+        return opIdKilledValues[opId];
+    }
+    private void setKilledValues(int opId, Object killedValues) {
+        opIdKilledValues[opId] = killedValues;
+    }
+
+    public void forEachKilled(LIRInstruction op, boolean end, ValueProcedure proc) {
+        Object entry = killedValues(op.id() + (end ? 1 : 0));
+        if (entry == null) {
+            // Nothing to do
+        } else if (entry instanceof CiValue) {
+            CiValue newValue = proc.doValue((CiValue) entry, null, null);
+            assert newValue == entry : "procedure does not allow to change values";
+        } else {
+            CiValue[] values = (CiValue[]) entry;
+            for (int i = 0; i < values.length; i++) {
+                if (values[i] != null) {
+                    CiValue newValue = proc.doValue(values[i], null, null);
+                    assert newValue == values[i] : "procedure does not allow to change values";
+                }
+            }
+        }
+    }
+
+    public int definition(Variable value) {
+        return definitions[value.index];
+    }
+
+    /**
+     * Numbers all instructions in all blocks. The numbering follows the {@linkplain ComputeLinearScanOrder linear scan order}.
+     */
+    private void numberInstructions() {
+        ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return setDef(value); } };
+
+        int numInstructions = 0;
+        for (Block block : blocks()) {
+            numInstructions += block.lir.size();
+        }
+        opIdBlock = new Block[numInstructions];
+        opIdKilledValues = new Object[numInstructions << 1];
+        definitions = new int[numVariables()];
+
+        curOpId = 0;
+        for (Block block : blocks()) {
+            for (LIRInstruction op : block.lir) {
+                op.setId(curOpId);
+                setBlockOf(curOpId, block);
+
+                op.forEachTemp(defProc);
+                op.forEachOutput(defProc);
+
+                curOpId += 2; // numbering of lirOps by two
+            }
+        }
+        assert curOpId == numInstructions << 1;
+    }
+
+    private CiValue setDef(CiValue value) {
+        if (isVariable(value)) {
+            assert definitions[asVariable(value).index] == 0 : "Variable defined twice";
+            definitions[asVariable(value).index] = curOpId;
+        }
+        return value;
+    }
+
+
+    private BitSet variableLive;
+    private BitSet registerLive;
+    private int curOpId;
+
+    private void backwardDataFlow() {
+        ValueProcedure inputProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId); } };
+        ValueProcedure aliveProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId + 1); } };
+        ValueProcedure tempProc =     new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value, true); } };
+        ValueProcedure outputProc =   new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value, false); } };
+
+        blockLiveIn = new BitSet[blocks().size()];
+        registerLive = new BitSet();
+
+        Debug.log("==== start backward data flow analysis ====");
+        for (int i = blocks().size() - 1; i >= 0; i--) {
+            Block block = blocks().get(i);
+            Debug.log("start block %s  loop %s", block, block.getLoop());
+
+            variableLive = new BitSet();
+            for (Block sux : block.getSuccessors()) {
+                BitSet suxLive = liveIn(sux);
+                if (suxLive != null) {
+                    Debug.log("  sux %s  suxLive: %s", sux, suxLive);
+                    variableLive.or(suxLive);
+                }
+            }
+
+            assert registerLive.isEmpty() : "no fixed register must be alive before processing a block";
+
+            for (int j = block.lir.size() - 1; j >= 0; j--) {
+                LIRInstruction op = block.lir.get(j);
+                curOpId = op.id();
+                Debug.log("  op %d %s  variableLive: %s  registerLive: %s", curOpId, op, variableLive, registerLive);
+
+                op.forEachOutput(outputProc);
+                op.forEachTemp(tempProc);
+                op.forEachState(aliveProc);
+                op.forEachAlive(aliveProc);
+                op.forEachInput(inputProc);
+            }
+
+            assert registerLive.isEmpty() : "no fixed register must be alive after processing a block";
+            assert liveIn(block) == null;
+            setLiveIn(block, variableLive);
+
+            if (block.isLoopHeader()) {
+                Debug.log("  loop header, propagating live set to loop blocks  variableLive: %s", variableLive);
+                // All variables that are live at the beginning of a loop are also live the whole loop.
+                // This is guaranteed by the SSA form.
+                for (Block loop : block.getLoop().blocks) {
+                    BitSet loopLiveIn = liveIn(loop);
+                    assert loopLiveIn != null : "All loop blocks must have been processed before the loop header";
+                    loopLiveIn.or(variableLive);
+                    Debug.log("    block %s  loopLiveIn %s", loop, loopLiveIn);
+                }
+            }
+
+            Debug.log("end block %s  variableLive: %s", block, variableLive);
+        }
+        Debug.log("==== end backward data flow analysis ====");
+    }
+
+    private CiValue use(CiValue value, int killOpId) {
+        Debug.log("    use %s", value);
+        if (isVariable(value)) {
+            int variableIdx = asVariable(value).index;
+            assert definitions[variableIdx] < curOpId;
+            if (!variableLive.get(variableIdx)) {
+                Debug.log("      set live variable %d", variableIdx);
+                variableLive.set(variableIdx);
+                kill(value, killOpId);
+            }
+
+        } else if (isAllocatableRegister(value)) {
+            int regNum = asRegister(value).number;
+            if (!registerLive.get(regNum)) {
+                Debug.log("      set live register %d", regNum);
+                registerLive.set(regNum);
+                kill(value, killOpId);
+            }
+        }
+        return value;
+    }
+
+    private CiValue def(CiValue value, boolean isTemp) {
+        Debug.log("    def %s", value);
+        if (isVariable(value)) {
+            int variableIdx = asVariable(value).index;
+            assert definitions[variableIdx] == curOpId;
+            if (variableLive.get(variableIdx)) {
+                Debug.log("      clear live variable %d", variableIdx);
+                assert !isTemp : "temp variable cannot be used after the operation";
+                variableLive.clear(variableIdx);
+            } else {
+                // Variable has never been used, so kill it immediately after the definition.
+                kill(value, curOpId + 1);
+            }
+
+        } else if (isAllocatableRegister(value)) {
+            int regNum = asRegister(value).number;
+            if (registerLive.get(regNum)) {
+                Debug.log("      clear live register %d", regNum);
+                assert !isTemp : "temp variable cannot be used after the operation";
+                registerLive.clear(regNum);
+            } else {
+                // Register has never been used, so kill it immediately after the definition.
+                kill(value, curOpId + 1);
+            }
+        }
+        return value;
+    }
+
+    private void kill(CiValue value, int opId) {
+        if (opId < 0) {
+            return;
+        }
+        if (isVariable(value)) {
+            int defOpId = definitions[asVariable(value).index];
+            assert defOpId > 0 && defOpId <= opId;
+
+            Block defBlock = blockOf(defOpId);
+            Block useBlock = blockOf(opId);
+
+            if (useBlock.getLoop() != null && useBlock.getLoop() != defBlock.getLoop()) {
+                // This is a value defined outside of the loop it is currently used in.  Therefore, it is live the whole loop
+                // and is not killed by the current instruction.
+                Debug.log("      no kill because use in %s, definition in %s", useBlock.getLoop(), defBlock.getLoop());
+                return;
+            }
+        }
+        Debug.log("      kill %s at %d", value, opId);
+
+        Object entry = killedValues(opId);
+        if (entry == null) {
+            setKilledValues(opId, value);
+        } else if (entry instanceof CiValue) {
+            setKilledValues(opId, new CiValue[] {(CiValue) entry, value});
+        } else {
+            CiValue[] killed = (CiValue[]) entry;
+            for (int i = 0; i < killed.length; i++) {
+                if (killed[i] == null) {
+                    killed[i] = value;
+                    return;
+                }
+            }
+            int oldLen = killed.length;
+            killed = Arrays.copyOf(killed, oldLen * 2);
+            setKilledValues(opId, killed);
+            killed[oldLen] = value;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.alloc.simple;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+import static com.oracle.max.graal.alloc.util.LocationUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ci.CiRegister.RegisterFlag;
+import com.oracle.max.graal.alloc.util.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.LIRInstruction.*;
+import com.oracle.max.graal.lir.cfg.*;
+
+public class LinearScanAllocator {
+    private final LIR lir;
+    private final FrameMap frameMap;
+
+    private final DataFlowAnalysis dataFlow;
+
+    public LinearScanAllocator(LIR lir, FrameMap frameMap) {
+        this.lir = lir;
+        this.frameMap = frameMap;
+
+        this.dataFlow = new DataFlowAnalysis(lir, frameMap.registerConfig);
+        this.blockBeginLocations = new LocationMap[lir.linearScanOrder().size()];
+        this.blockEndLocations = new LocationMap[lir.linearScanOrder().size()];
+        this.moveResolver = new MoveResolverImpl(lir, frameMap);
+
+        this.variableLastUse = new int[lir.numVariables()];
+    }
+
+    private class MoveResolverImpl extends MoveResolver {
+        public MoveResolverImpl(LIR lir, FrameMap frameMap) {
+            super(lir, frameMap);
+        }
+
+        @Override
+        protected CiValue scratchRegister(Variable spilled) {
+            GraalInternalError.shouldNotReachHere("needs working implementation");
+
+            EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters();
+            CiRegister[] availableRegs = categorizedRegs.get(spilled.flag);
+            for (CiRegister reg : availableRegs) {
+                if (curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null) {
+                    return reg.asValue(spilled.kind);
+                }
+            }
+            throw new CiBailout("No register found");
+        }
+    }
+
+    private class ResolveDataFlowImpl extends ResolveDataFlow {
+        public ResolveDataFlowImpl(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) {
+            super(lir, moveResolver, dataFlow);
+        }
+
+        @Override
+        protected LocationMap locationsForBlockBegin(Block block) {
+            return beginLocationsFor(block);
+        }
+
+        @Override
+        protected LocationMap locationsForBlockEnd(Block block) {
+            return endLocationsFor(block);
+        }
+    }
+
+    private class AssignRegistersImpl extends AssignRegisters {
+        public AssignRegistersImpl(LIR lir, FrameMap frameMap) {
+            super(lir, frameMap);
+        }
+
+        @Override
+        protected LocationMap locationsForBlockEnd(Block block) {
+            return endLocationsFor(block);
+        }
+    }
+
+
+    private int maxRegisterNum() {
+        return frameMap.target.arch.registers.length;
+    }
+
+    private boolean isAllocatableRegister(CiValue value) {
+        return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
+    }
+
+
+    private final LocationMap[] blockBeginLocations;
+
+    private LocationMap beginLocationsFor(Block block) {
+        return blockBeginLocations[block.getId()];
+    }
+    private void setBeginLocationsFor(Block block, LocationMap locations) {
+        blockBeginLocations[block.getId()] = locations;
+    }
+
+    private final LocationMap[] blockEndLocations;
+
+    private LocationMap endLocationsFor(Block block) {
+        return blockEndLocations[block.getId()];
+    }
+    private void setEndLocationsFor(Block block, LocationMap locations) {
+        blockEndLocations[block.getId()] = locations;
+    }
+
+    private final int[] variableLastUse;
+
+    private int lastUseFor(Variable variable) {
+        return variableLastUse[variable.index];
+    }
+
+    private void setLastUseFor(Variable variable, int lastUse) {
+        variableLastUse[variable.index] = lastUse;
+    }
+
+    private MoveResolver moveResolver;
+    private LocationMap curLocations;
+    private CiValue[] curInRegisterState;
+    private CiValue[] curOutRegisterState;
+    private BitSet curLiveIn;
+    private int curOpId;
+    private boolean curPhiDefs;
+
+    private LocationMap canonicalSpillLocations;
+
+    public void execute() {
+        assert LIRVerifier.verify(true, lir, frameMap);
+
+        dataFlow.execute();
+        IntervalPrinter.printBeforeAllocation("Before register allocation", lir, frameMap.registerConfig, dataFlow);
+
+        allocate();
+
+        IntervalPrinter.printAfterAllocation("After linear scan allocation", lir, frameMap.registerConfig, dataFlow, blockEndLocations);
+
+        ResolveDataFlow resolveDataFlow = new ResolveDataFlowImpl(lir, moveResolver, dataFlow);
+        resolveDataFlow.execute();
+        frameMap.finish();
+
+        IntervalPrinter.printAfterAllocation("After resolve data flow", lir, frameMap.registerConfig, dataFlow, blockEndLocations);
+        assert RegisterVerifier.verify(lir, frameMap);
+
+        AssignRegisters assignRegisters = new AssignRegistersImpl(lir, frameMap);
+        assignRegisters.execute();
+
+        Debug.dump(lir, "After register asignment");
+        assert LIRVerifier.verify(false, lir, frameMap);
+    }
+
+    private void allocate() {
+        ValueProcedure recordUseProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return recordUse(value); } };
+        ValueProcedure killNonLiveProc =  new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killNonLive(value); } };
+        ValueProcedure unblockProc =      new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return unblock(value); } };
+        ValueProcedure killProc =         new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value); } };
+        ValueProcedure blockProc =        new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return block(value); } };
+        ValueProcedure useProc =          new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
+        ValueProcedure defProc =          new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } };
+
+        Debug.log("==== start linear scan allocation ====");
+        canonicalSpillLocations = new LocationMap(lir.numVariables());
+        curInRegisterState = new CiValue[maxRegisterNum()];
+        curOutRegisterState = new CiValue[maxRegisterNum()];
+        for (Block block : lir.linearScanOrder()) {
+            Debug.log("start block %s %s", block, block.getLoop());
+
+            Arrays.fill(curOutRegisterState, null);
+            if (block.getDominator() != null) {
+                LocationMap dominatorState = endLocationsFor(block.getDominator());
+                curLocations = new LocationMap(dominatorState);
+                // Clear out all variables that are not live at the begin of this block
+                curLiveIn = dataFlow.liveIn(block);
+                curLocations.forEachLocation(killNonLiveProc);
+                assert checkInputState(block);
+            } else {
+                curLocations = new LocationMap(lir.numVariables());
+            }
+            Debug.log(logCurrentState());
+
+            for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) {
+                LIRInstruction op = block.lir.get(opIdx);
+                curOpId = op.id();
+                curPhiDefs = opIdx == 0;
+
+                Debug.log("  op %d %s", op.id(), op);
+
+                System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length);
+
+                // Unblock fixed registers that are only used for inputs in curOutRegisterState.
+                dataFlow.forEachKilled(op, false, unblockProc);
+                // Block fixed registers defined by this instruction in curOutRegisterState.
+                op.forEachTemp(blockProc);
+                op.forEachOutput(blockProc);
+
+                op.forEachInput(recordUseProc);
+                op.forEachAlive(recordUseProc);
+
+                moveResolver.init(block.lir, opIdx);
+                // Process Alive before Input because they are more restricted and the same variable can be Alive and Input.
+                op.forEachAlive(useProc);
+                op.forEachInput(useProc);
+
+                dataFlow.forEachKilled(op, false, killProc);
+
+                if (op.hasCall()) {
+                    spillCallerSaveRegisters();
+                }
+
+                op.forEachTemp(defProc);
+                op.forEachOutput(defProc);
+
+                // Fixed temp and output registers can evict variables from their assigned register, allocate new location for them.
+                fixupEvicted();
+                // State values are the least critical and can get the leftover registers (or stack slots if no more register available).
+                op.forEachState(useProc);
+
+                if (opIdx == 0) {
+                    assert !moveResolver.hasMappings() : "cannot insert spill moves before label";
+                    setBeginLocationsFor(block, new LocationMap(curLocations));
+                }
+                moveResolver.resolve();
+
+                dataFlow.forEachKilled(op, true, unblockProc);
+                dataFlow.forEachKilled(op, true, killProc);
+
+                curOpId = -1;
+            }
+
+            assert endLocationsFor(block) == null;
+            setEndLocationsFor(block, curLocations);
+
+            logCurrentState();
+            Debug.log("end block %s", block);
+        }
+
+        moveResolver.finish();
+        Debug.log("==== end linear scan allocation ====");
+    }
+
+    private CiValue killNonLive(CiValue value) {
+        assert isLocation(value);
+        if (!curLiveIn.get(asLocation(value).variable.index)) {
+            return null;
+
+        } else if (isAllocatableRegister(asLocation(value).location)) {
+            int regNum = asRegister(asLocation(value).location).number;
+            assert curOutRegisterState[regNum] == null;
+            curOutRegisterState[regNum] = value;
+        }
+        return value;
+    }
+
+    private CiValue unblock(CiValue value) {
+        if (isAllocatableRegister(value)) {
+            Debug.log("    unblock register %s", value);
+            int regNum = asRegister(value).number;
+            assert curOutRegisterState[regNum] == value;
+            curOutRegisterState[regNum] = null;
+        }
+        return value;
+    }
+
+    private CiValue kill(CiValue value) {
+        if (isVariable(value)) {
+            Location location = curLocations.get(asVariable(value));
+            Debug.log("    kill location %s", location);
+            if (isRegister(location.location)) {
+                int regNum = asRegister(location.location).number;
+                if (curOutRegisterState[regNum] == location) {
+                    curOutRegisterState[regNum] = null;
+                }
+            }
+            curLocations.clear(asVariable(value));
+        }
+        return value;
+    }
+
+
+    private CiValue block(CiValue value) {
+        if (isAllocatableRegister(value)) {
+            Debug.log("    block %s", value);
+            int regNum = asRegister(value).number;
+            assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof Location;
+            curOutRegisterState[regNum] = value;
+        }
+        return value;
+    }
+
+    private void spillCallerSaveRegisters() {
+        Debug.log("    spill caller save registers in curInRegisterState %s", Arrays.toString(curInRegisterState));
+        for (CiRegister reg : frameMap.registerConfig.getCallerSaveRegisters()) {
+            CiValue in = curInRegisterState[reg.number];
+            if (in != null && isLocation(in)) {
+                spill(asLocation(in));
+            }
+        }
+    }
+
+    private CiValue recordUse(CiValue value) {
+        if (isVariable(value)) {
+            assert lastUseFor(asVariable(value)) <= curOpId;
+            setLastUseFor(asVariable(value), curOpId);
+
+        }
+        return value;
+    }
+
+    private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        assert mode == OperandMode.Input || mode == OperandMode.Alive;
+        if (isVariable(value)) {
+            // State values are not recorded beforehand because it does not matter if they are spilled. Still, it is necessary to record them as used now.
+            recordUse(value);
+
+            Location curLoc = curLocations.get(asVariable(value));
+            if (isStackSlot(curLoc.location) && flags.contains(OperandFlag.Stack)) {
+                Debug.log("    use %s %s: use current stack slot %s", mode, value, curLoc.location);
+                return curLoc;
+            }
+            if (isRegister(curLoc.location)) {
+                int regNum = asRegister(curLoc.location).number;
+                assert curInRegisterState[regNum] == curLoc;
+                if (mode == OperandMode.Input || curOutRegisterState[regNum] == curLoc) {
+                    Debug.log("    use %s %s: use current register %s", mode, value, curLoc.location);
+                    return curLoc;
+                }
+            }
+
+            Debug.log("    use %s %s", mode, value);
+
+            Location newLoc = allocateRegister(asVariable(value), mode, flags);
+            if (newLoc != curLoc) {
+                moveResolver.add(curLoc, newLoc);
+            }
+            return newLoc;
+        } else {
+            assert !isAllocatableRegister(value) || curInRegisterState[asRegister(value).number] == value;
+        }
+        return value;
+    }
+
+    private static final EnumSet<OperandFlag> SPILL_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+
+    private CiValue def(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        assert mode == OperandMode.Temp || mode == OperandMode.Output;
+        if (isVariable(value)) {
+            Debug.log("    def %s %s", mode, value);
+            assert curLocations.get(asVariable(value)) == null;
+
+            Location newLoc = allocateRegister(asVariable(value), mode, flags);
+            return newLoc;
+        }
+        return value;
+    }
+
+
+    private void fixupEvicted() {
+        for (int i = 0; i < curInRegisterState.length; i++) {
+            CiValue in = curInRegisterState[i];
+            CiValue out = curOutRegisterState[i];
+
+            if (in != null && in != out && isLocation(in) && curLocations.get(asLocation(in).variable) == in) {
+                Debug.log("    %s was evicted by %s, need to allocate new location", in, out);
+                Location oldLoc = asLocation(in);
+                Location newLoc = allocateRegister(oldLoc.variable, OperandMode.Alive, SPILL_FLAGS);
+                assert oldLoc != newLoc;
+                moveResolver.add(oldLoc, newLoc);
+            }
+
+
+        }
+    }
+
+
+    private Location allocateRegister(final Variable variable, OperandMode mode, EnumSet<OperandFlag> flags) {
+//        if (flags.contains(OperandFlag.RegisterHint)) {
+//            CiValue result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() {
+//                @Override
+//                public CiValue doValue(CiValue registerHint) {
+//                    Debug.log("      registerHint %s", registerHint);
+//                    CiRegister hint = null;
+//                    if (isRegister(registerHint)) {
+//                        hint = asRegister(registerHint);
+//                    } else if (isLocation(registerHint) && isRegister(asLocation(registerHint).location)) {
+//                        hint = asRegister(asLocation(registerHint).location);
+//                    }
+//                    if (hint != null && hint.isSet(variable.flag) && isFree(hint, inRegisterState, outRegisterState)) {
+//                        return selectRegister(hint, variable, inRegisterState, outRegisterState);
+//                    }
+//                    return null;
+//                }
+//            });
+//
+//            if (result != null) {
+//                return asLocation(result);
+//            }
+//        }
+//
+        EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters();
+        CiRegister[] availableRegs = categorizedRegs.get(variable.flag);
+
+        Location bestSpillCandidate = null;
+        for (CiRegister reg : availableRegs) {
+            if (isFree(reg, mode)) {
+                return selectRegister(reg, variable, mode);
+            } else {
+                Location spillCandidate = spillCandidate(reg);
+                if (betterSpillCandidate(spillCandidate, bestSpillCandidate)) {
+                    bestSpillCandidate = spillCandidate;
+                }
+            }
+        }
+
+        if (flags.contains(OperandFlag.Stack) && betterSpillCandidate(curLocations.get(variable), bestSpillCandidate)) {
+            return selectSpillSlot(variable);
+        }
+
+        if (bestSpillCandidate == null) {
+            if (curPhiDefs) {
+                return selectSpillSlot(variable);
+            }
+
+            // This should not happen as long as all LIR instructions have fulfillable register constraints. But be safe in product mode and bail out.
+            assert false;
+            throw new CiBailout("No register available");
+        }
+
+        spill(bestSpillCandidate);
+
+        return selectRegister(asRegister(bestSpillCandidate.location), variable, mode);
+    }
+
+    private void spill(Location value) {
+        Location newLoc = spillLocation(value.variable);
+        Debug.log("      spill %s to %s", value, newLoc);
+        if (!curPhiDefs) {
+            moveResolver.add(value, newLoc);
+        }
+        curLocations.put(newLoc);
+
+        CiRegister reg = asRegister(value.location);
+        assert curInRegisterState[reg.number] == value;
+        curInRegisterState[reg.number] = null;
+        if (curOutRegisterState[reg.number] == value) {
+            curOutRegisterState[reg.number] = null;
+        }
+    }
+
+    private boolean isFree(CiRegister reg, OperandMode mode) {
+        switch (mode) {
+            case Input:  return curInRegisterState[reg.number] == null;
+            case Alive:  return curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null;
+            case Temp:   return curOutRegisterState[reg.number] == null;
+            case Output: return curOutRegisterState[reg.number] == null;
+            default:     throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private Location spillCandidate(CiRegister reg) {
+        CiValue in = curInRegisterState[reg.number];
+        CiValue out = curOutRegisterState[reg.number];
+        if (in == out && in != null && isLocation(in) && lastUseFor(asLocation(in).variable) < curOpId) {
+            return asLocation(in);
+        }
+        return null;
+    }
+
+    private boolean betterSpillCandidate(Location loc, Location compare) {
+        if (loc == null) {
+            return false;
+        }
+        if (compare == null) {
+            return true;
+        }
+        if (canonicalSpillLocations.get(loc.variable) != null && canonicalSpillLocations.get(compare.variable) == null) {
+            return true;
+        }
+        return dataFlow.definition(loc.variable) < dataFlow.definition(compare.variable);
+    }
+
+    private Location spillLocation(Variable variable) {
+        Location result = canonicalSpillLocations.get(variable);
+        if (result == null) {
+            result = new Location(variable, frameMap.allocateSpillSlot(variable.kind));
+            canonicalSpillLocations.put(result);
+        }
+        return result;
+    }
+
+    private Location selectRegister(CiRegister reg, Variable variable, OperandMode mode) {
+        assert isFree(reg, mode);
+
+        Location loc = new Location(variable, reg.asValue(variable.kind));
+        if (mode == OperandMode.Input || mode == OperandMode.Alive) {
+            curInRegisterState[reg.number] = loc;
+        }
+        curOutRegisterState[reg.number] = loc;
+        curLocations.put(loc);
+        recordUse(variable);
+
+        Debug.log("      selected register %s", loc);
+        return loc;
+    }
+
+    private Location selectSpillSlot(Variable variable) {
+        Location loc = spillLocation(variable);
+        curLocations.put(loc);
+        recordUse(variable);
+
+        Debug.log("      selected spill slot %s", loc);
+        return loc;
+    }
+
+    private boolean checkInputState(final Block block) {
+        final BitSet liveState = new BitSet();
+        curLocations.forEachLocation(new ValueProcedure() {
+            @Override
+            public CiValue doValue(CiValue value) {
+                liveState.set(asLocation(value).variable.index);
+
+                for (Block pred : block.getPredecessors()) {
+                    LocationMap predState = endLocationsFor(pred);
+                    if (predState != null) {
+                        assert predState.get(asLocation(value).variable) != null;
+                    } else {
+                        assert block.isLoopHeader();
+                    }
+                }
+                return value;
+            }
+        });
+        assert liveState.equals(curLiveIn);
+        return true;
+    }
+
+
+    private String logCurrentState() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("  current lcoations: ");
+        curLocations.forEachLocation(new ValueProcedure() {
+            @Override
+            public CiValue doValue(CiValue value) {
+                sb.append(value).append(" ");
+                return value;
+            }
+        });
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.alloc.simple;
+
+import static com.oracle.max.graal.alloc.util.LocationUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.alloc.util.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.LIRInstruction.*;
+import com.oracle.max.graal.lir.StandardOp.*;
+import com.oracle.max.graal.lir.cfg.*;
+
+public abstract class ResolveDataFlow {
+    public final LIR lir;
+    public final MoveResolver moveResolver;
+    public final DataFlowAnalysis dataFlow;
+
+    public ResolveDataFlow(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) {
+        this.lir = lir;
+        this.moveResolver = moveResolver;
+        this.dataFlow = dataFlow;
+    }
+
+    private LocationMap curFromLocations;
+
+    public void execute() {
+        ValueProcedure locMappingProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return locMapping(value); } };
+
+        Debug.log("==== start resolve data flow ====");
+        for (Block toBlock : lir.linearScanOrder()) {
+            PhiLabelOp phiDefs = null;
+            if (toBlock.lir.get(0) instanceof PhiLabelOp) {
+                phiDefs = (PhiLabelOp) toBlock.lir.get(0);
+            }
+
+            for (Block fromBlock : toBlock.getPredecessors()) {
+                Debug.log("start edge %s -> %s", fromBlock, toBlock);
+                findInsertPos(fromBlock, toBlock);
+
+                LocationMap toLocations = locationsForBlockBegin(toBlock);
+                curFromLocations = locationsForBlockEnd(fromBlock);
+                if (toLocations != curFromLocations) {
+                    toLocations.forEachLocation(locMappingProc);
+                }
+
+                if (phiDefs != null) {
+                    PhiJumpOp phiInputs = (PhiJumpOp) fromBlock.lir.get(fromBlock.lir.size() - 1);
+                    phiMapping(phiInputs.getPhiInputs(), phiDefs.getPhiDefinitions());
+                    phiInputs.markResolved();
+                }
+
+                moveResolver.resolve();
+                Debug.log("end edge %s -> %s", fromBlock, toBlock);
+            }
+
+            if (phiDefs != null) {
+                // Phi functions are resolved with moves now, so delete them.
+                phiDefs.markResolved();
+            }
+        }
+        moveResolver.finish();
+        Debug.log("==== end resolve data flow ====");
+    }
+
+    private CiValue locMapping(CiValue value) {
+        Location to = asLocation(value);
+        Location from = curFromLocations.get(to.variable);
+        if (value != from && from != null) {
+            moveResolver.add(from, to);
+        }
+        return value;
+    }
+
+    private void phiMapping(CiValue[] inputs, CiValue[] outputs) {
+        assert inputs.length == outputs.length;
+        for (int i = 0; i < inputs.length; i++) {
+            if (inputs[i] != outputs[i]) {
+                moveResolver.add(inputs[i], asLocation(outputs[i]));
+            }
+        }
+    }
+
+    private void findInsertPos(Block fromBlock, Block toBlock) {
+        assert fromBlock.getSuccessors().contains(toBlock) && toBlock.getPredecessors().contains(fromBlock);
+
+        if (fromBlock.numberOfSux() == 1) {
+            List<LIRInstruction> instructions = fromBlock.lir;
+            LIRInstruction instr = instructions.get(instructions.size() - 1);
+            assert instr instanceof StandardOp.JumpOp : "block does not end with an unconditional jump";
+            moveResolver.init(instructions, instructions.size() - 1);
+            Debug.log("  insert at end of %s before %d", fromBlock, instructions.size() - 1);
+
+        } else if (toBlock.numberOfPreds() == 1) {
+            moveResolver.init(toBlock.lir, 1);
+            Debug.log("  insert at beginning of %s before %d", toBlock, 1);
+
+        } else {
+            GraalInternalError.shouldNotReachHere("Critical edge not split");
+        }
+    }
+
+    protected abstract LocationMap locationsForBlockBegin(Block block);
+    protected abstract LocationMap locationsForBlockEnd(Block block);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.alloc.simple;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+import static com.oracle.max.graal.alloc.util.LocationUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ci.CiRegister.RegisterFlag;
+import com.oracle.max.graal.alloc.util.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.LIRInstruction.*;
+import com.oracle.max.graal.lir.cfg.*;
+
+public class SpillAllAllocator {
+    private final LIR lir;
+    private final FrameMap frameMap;
+
+    private final DataFlowAnalysis dataFlow;
+
+    public SpillAllAllocator(LIR lir, FrameMap frameMap) {
+        this.lir = lir;
+        this.frameMap = frameMap;
+
+        this.dataFlow = new DataFlowAnalysis(lir, frameMap.registerConfig);
+        this.blockLocations = new LocationMap[lir.linearScanOrder().size()];
+        this.moveResolver = new MoveResolverImpl(lir, frameMap);
+    }
+
+    private class MoveResolverImpl extends MoveResolver {
+        public MoveResolverImpl(LIR lir, FrameMap frameMap) {
+            super(lir, frameMap);
+        }
+
+        @Override
+        protected CiValue scratchRegister(Variable spilled) {
+            EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters();
+            CiRegister[] availableRegs = categorizedRegs.get(spilled.flag);
+            for (CiRegister reg : availableRegs) {
+                if (curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null) {
+                    return reg.asValue(spilled.kind);
+                }
+            }
+            throw new CiBailout("No register found");
+        }
+    }
+
+    private class ResolveDataFlowImpl extends ResolveDataFlow {
+        public ResolveDataFlowImpl(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) {
+            super(lir, moveResolver, dataFlow);
+        }
+
+        @Override
+        protected LocationMap locationsForBlockBegin(Block block) {
+            assert block.numberOfPreds() > 0 && block.getDominator() != null;
+            return locationsFor(block.getDominator());
+        }
+
+        @Override
+        protected LocationMap locationsForBlockEnd(Block block) {
+            return locationsFor(block);
+        }
+    }
+
+    private class AssignRegistersImpl extends AssignRegisters {
+        public AssignRegistersImpl(LIR lir, FrameMap frameMap) {
+            super(lir, frameMap);
+        }
+
+        @Override
+        protected LocationMap locationsForBlockEnd(Block block) {
+            return locationsFor(block);
+        }
+    }
+
+
+    private int maxRegisterNum() {
+        return frameMap.target.arch.registers.length;
+    }
+
+    private boolean isAllocatableRegister(CiValue value) {
+        return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
+    }
+
+
+    private final LocationMap[] blockLocations;
+
+    private LocationMap locationsFor(Block block) {
+        return blockLocations[block.getId()];
+    }
+    private void setLocationsFor(Block block, LocationMap locations) {
+        blockLocations[block.getId()] = locations;
+    }
+
+    private MoveResolver moveResolver;
+    private LocationMap curStackLocations;
+    private LocationMap curRegisterLocations;
+    private Object[] curInRegisterState;
+    private Object[] curOutRegisterState;
+    private BitSet curLiveIn;
+    private LIRInstruction curInstruction;
+
+    public void execute() {
+        assert LIRVerifier.verify(true, lir, frameMap);
+
+        dataFlow.execute();
+        IntervalPrinter.printBeforeAllocation("Before register allocation", lir, frameMap.registerConfig, dataFlow);
+
+        allocate();
+
+        IntervalPrinter.printAfterAllocation("After spill all allocation", lir, frameMap.registerConfig, dataFlow, blockLocations);
+
+        ResolveDataFlow resolveDataFlow = new ResolveDataFlowImpl(lir, moveResolver, dataFlow);
+        resolveDataFlow.execute();
+        frameMap.finish();
+
+        IntervalPrinter.printAfterAllocation("After resolve data flow", lir, frameMap.registerConfig, dataFlow, blockLocations);
+        assert RegisterVerifier.verify(lir, frameMap);
+
+        AssignRegisters assignRegisters = new AssignRegistersImpl(lir, frameMap);
+        assignRegisters.execute();
+
+        Debug.dump(lir, "After register asignment");
+        assert LIRVerifier.verify(false, lir, frameMap);
+    }
+
+    private void allocate() {
+        ValueProcedure killNonLiveProc =  new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killNonLive(value); } };
+        ValueProcedure killBeginProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, false); } };
+        ValueProcedure killEndProc =      new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, true); } };
+        ValueProcedure killLocationProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killLocation(value); } };
+        ValueProcedure blockProc =        new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return block(value); } };
+        ValueProcedure loadProc =         new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return load(value, mode, flags); } };
+        ValueProcedure spillProc =        new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return spill(value, mode, flags); } };
+        ValueProcedure useSlotProc =      new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return useSlot(value); } };
+
+        Debug.log("==== start spill all allocation ====");
+        curInRegisterState = new Object[maxRegisterNum()];
+        curOutRegisterState = new Object[maxRegisterNum()];
+        curRegisterLocations = new LocationMap(lir.numVariables());
+        for (Block block : lir.linearScanOrder()) {
+            Debug.log("start block %s %s", block, block.getLoop());
+            assert checkEmpty(curOutRegisterState);
+
+            if (block.getDominator() != null) {
+                LocationMap dominatorState = locationsFor(block.getDominator());
+                curStackLocations = new LocationMap(dominatorState);
+                // Clear out all variables that are not live at the begin of this block
+                curLiveIn = dataFlow.liveIn(block);
+                curStackLocations.forEachLocation(killNonLiveProc);
+                assert checkInputState(block);
+            } else {
+                curStackLocations = new LocationMap(lir.numVariables());
+            }
+            Debug.log(logCurrentState());
+
+            for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) {
+                LIRInstruction op = block.lir.get(opIdx);
+                curInstruction = op;
+                Debug.log("  op %d %s", op.id(), op);
+
+                assert curRegisterLocations.checkEmpty();
+
+                System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length);
+
+                // Block fixed registers that are defined by this instruction, so that they are no longer available for normal allocation.
+                op.forEachTemp(blockProc);
+                op.forEachOutput(blockProc);
+
+                moveResolver.init(block.lir, opIdx);
+                // Process Alive before Input because they are more restricted and the same variable can be Alive and Input.
+                op.forEachAlive(loadProc);
+                op.forEachInput(loadProc);
+                moveResolver.resolve();
+                op.forEachState(useSlotProc);
+
+                dataFlow.forEachKilled(op, false, killBeginProc);
+                assert !op.hasCall() || checkNoCallerSavedRegister() : "caller saved register in use accross call site";
+
+                moveResolver.init(block.lir, opIdx + 1);
+                op.forEachTemp(spillProc);
+                op.forEachOutput(spillProc);
+                moveResolver.resolve();
+
+                dataFlow.forEachKilled(op, true, killEndProc);
+                curRegisterLocations.forEachLocation(killLocationProc);
+
+                assert curRegisterLocations.checkEmpty();
+                curInstruction = null;
+            }
+            assert checkEmpty(curOutRegisterState);
+            assert locationsFor(block) == null;
+            setLocationsFor(block, curStackLocations);
+
+            logCurrentState();
+            Debug.log("end block %s", block);
+        }
+
+        moveResolver.finish();
+        Debug.log("==== end spill all allocation ====");
+    }
+
+    private CiValue killNonLive(CiValue value) {
+        assert isLocation(value);
+        if (!curLiveIn.get(asLocation(value).variable.index)) {
+            return null;
+        }
+        return value;
+    }
+
+    private CiValue kill(CiValue value, boolean end) {
+        if (isVariable(value)) {
+            Debug.log("    kill variable %s", value);
+
+            Variable variable = asVariable(value);
+            curStackLocations.clear(variable);
+
+            Location loc = curRegisterLocations.get(variable);
+            if (loc != null) {
+                killLocation(loc);
+                curRegisterLocations.clear(variable);
+
+                Debug.log("      location %s", loc);
+                assert isAllocatableRegister(loc.location);
+
+                int regNum = asRegister(loc.location).number;
+                if (curOutRegisterState[regNum] == loc) {
+                    curOutRegisterState[regNum] = null;
+                }
+            }
+
+        } else if (isAllocatableRegister(value)) {
+            Debug.log("    kill register %s", value);
+            int regNum = asRegister(value).number;
+            assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof LIRInstruction && curInstruction != null;
+
+            if (end || curOutRegisterState[regNum] != curInstruction) {
+                curOutRegisterState[regNum] = null;
+            }
+
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+        return value;
+    }
+
+    private CiValue killLocation(CiValue value) {
+        Debug.log("    kill location %s", value);
+        assert isAllocatableRegister(asLocation(value).location);
+
+        int regNum = asRegister(asLocation(value).location).number;
+        if (curOutRegisterState[regNum] == value) {
+            curOutRegisterState[regNum] = null;
+        }
+        return null;
+    }
+
+    private CiValue block(CiValue value) {
+        if (isAllocatableRegister(value)) {
+            Debug.log("    block %s", value);
+            int regNum = asRegister(value).number;
+            assert curInstruction != null;
+            assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof LIRInstruction;
+            curOutRegisterState[regNum] = curInstruction;
+        }
+        return value;
+    }
+
+    private CiValue load(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        assert mode == OperandMode.Input || mode == OperandMode.Alive;
+        if (flags.contains(OperandFlag.Stack)) {
+            return useSlot(value);
+        }
+        if (isVariable(value)) {
+            Debug.log("    load %s", value);
+            Location regLoc = curRegisterLocations.get(asVariable(value));
+            if (regLoc != null) {
+                // This variable has already been processed before.
+                Debug.log("      found location %s", regLoc);
+            } else {
+                regLoc = allocateRegister(asVariable(value), curInRegisterState, mode == OperandMode.Alive ? curOutRegisterState : null, mode, flags);
+                Location stackLoc = curStackLocations.get(asVariable(value));
+                assert stackLoc != null;
+                moveResolver.add(stackLoc, regLoc);
+            }
+            return regLoc;
+        } else {
+            assert !isAllocatableRegister(value) || curInRegisterState[asRegister(value).number] instanceof LIRInstruction;
+            return value;
+        }
+    }
+
+    private CiValue spill(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        assert mode == OperandMode.Temp || mode == OperandMode.Output;
+        if (flags.contains(OperandFlag.Stack)) {
+            return defSlot(value);
+        }
+        if (isVariable(value)) {
+            Debug.log("    spill %s", value);
+            assert curStackLocations.get(asVariable(value)) == null;
+            Location regLoc = allocateRegister(asVariable(value), null, curOutRegisterState, mode, flags);
+            if (mode == OperandMode.Output) {
+                Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind));
+                curStackLocations.put(stackLoc);
+                moveResolver.add(regLoc, stackLoc);
+            }
+            return regLoc;
+        } else {
+            assert !isAllocatableRegister(value) || curOutRegisterState[asRegister(value).number] == curInstruction && curInstruction != null;
+            return value;
+        }
+    }
+
+    private CiValue useSlot(CiValue value) {
+        if (isVariable(value)) {
+            Debug.log("    useSlot %s", value);
+            Location stackLoc = curStackLocations.get(asVariable(value));
+            assert stackLoc != null;
+            Debug.log("      slot %s", stackLoc);
+            return stackLoc;
+        } else {
+            return value;
+        }
+    }
+
+    private CiValue defSlot(CiValue value) {
+        if (isVariable(value)) {
+            Debug.log("    assignSlot %s", value);
+            Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind));
+            assert curStackLocations.get(asVariable(value)) == null;
+            curStackLocations.put(stackLoc);
+            Debug.log("      slot %s", stackLoc);
+            return stackLoc;
+        } else {
+            return value;
+        }
+    }
+
+    private Location allocateRegister(final Variable variable, final Object[] inRegisterState, final Object[] outRegisterState, OperandMode mode, EnumSet<OperandFlag> flags) {
+        if (flags.contains(OperandFlag.RegisterHint)) {
+            CiValue result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() {
+                @Override
+                public CiValue doValue(CiValue registerHint) {
+                    Debug.log("      registerHint %s", registerHint);
+                    CiRegister hint = null;
+                    if (isRegister(registerHint)) {
+                        hint = asRegister(registerHint);
+                    } else if (isLocation(registerHint) && isRegister(asLocation(registerHint).location)) {
+                        hint = asRegister(asLocation(registerHint).location);
+                    }
+                    if (hint != null && hint.isSet(variable.flag) && isFree(hint, inRegisterState, outRegisterState)) {
+                        return selectRegister(hint, variable, inRegisterState, outRegisterState);
+                    }
+                    return null;
+                }
+            });
+
+            if (result != null) {
+                return asLocation(result);
+            }
+        }
+
+        EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters();
+        CiRegister[] availableRegs = categorizedRegs.get(variable.flag);
+
+        for (CiRegister reg : availableRegs) {
+            if (isFree(reg, inRegisterState, outRegisterState)) {
+                return selectRegister(reg, variable, inRegisterState, outRegisterState);
+            }
+
+        }
+        throw new CiBailout("No register found");
+    }
+
+    private static boolean isFree(CiRegister reg, Object[] inRegisterState, Object[] outRegisterState) {
+        return (inRegisterState == null || inRegisterState[reg.number] == null) && (outRegisterState == null || outRegisterState[reg.number] == null);
+    }
+
+    private Location selectRegister(CiRegister reg, Variable variable, Object[] inRegisterState, Object[] outRegisterState) {
+        Location loc = new Location(variable, reg.asValue(variable.kind));
+        if (inRegisterState != null) {
+            inRegisterState[reg.number] = loc;
+        }
+        if (outRegisterState != null) {
+            outRegisterState[reg.number] = loc;
+        }
+        assert curRegisterLocations.get(variable) == null;
+        curRegisterLocations.put(loc);
+        Debug.log("      selected register %s", loc);
+        return loc;
+    }
+
+    private boolean checkInputState(final Block block) {
+        final BitSet liveState = new BitSet();
+        curStackLocations.forEachLocation(new ValueProcedure() {
+            @Override
+            public CiValue doValue(CiValue value) {
+                liveState.set(asLocation(value).variable.index);
+
+                for (Block pred : block.getPredecessors()) {
+                    LocationMap predState = locationsFor(pred);
+                    if (predState != null) {
+                        assert predState.get(asLocation(value).variable) == value;
+                    } else {
+                        assert block.isLoopHeader();
+                    }
+                }
+                return value;
+            }
+        });
+        assert liveState.equals(curLiveIn);
+        return true;
+    }
+
+    private boolean checkNoCallerSavedRegister() {
+        for (CiRegister reg : frameMap.registerConfig.getCallerSaveRegisters()) {
+            assert curOutRegisterState[reg.number] == null || curOutRegisterState[reg.number] == curInstruction : "caller saved register in use accross call site";
+        }
+        return true;
+    }
+
+    private static boolean checkEmpty(Object[] array) {
+        for (Object o : array) {
+            assert o == null;
+        }
+        return true;
+    }
+
+
+    private String logCurrentState() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("  curVariableLocations: ");
+        curStackLocations.forEachLocation(new ValueProcedure() {
+            @Override
+            public CiValue doValue(CiValue value) {
+                sb.append(value).append(" ");
+                return value;
+            }
+        });
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.alloc.util;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+import static com.oracle.max.graal.alloc.util.LocationUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.alloc.simple.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.LIRInstruction.*;
+import com.oracle.max.graal.lir.cfg.*;
+
+public final class IntervalPrinter {
+
+    public static void printBeforeAllocation(String label, LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow) {
+        if (Debug.isDumpEnabled()) {
+            IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, null);
+            Debug.dump(lir, label);
+            Debug.dump(printer.execute(), label);
+        }
+    }
+
+    public static void printAfterAllocation(String label, LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow, LocationMap[] blockEndLocations) {
+        if (Debug.isDumpEnabled()) {
+            IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, blockEndLocations);
+            Debug.dump(lir, label);
+            Debug.dump(printer.execute(), label);
+        }
+    }
+
+
+    public static class Range {
+        public final int from;
+        public final int to;
+
+        public Range(int from, int to) {
+            this.from = from;
+            this.to = to;
+        }
+    }
+
+    public static class UsePosition {
+        public final int pos;
+        public final String kind;
+
+        public UsePosition(int pos, String kind) {
+            this.pos = pos;
+            this.kind = kind;
+        }
+    }
+
+    public static class Interval {
+        public final String name;
+        public final String description;
+        public final String variable;
+        public final String type;
+        public final List<Range> ranges;
+        public final List<UsePosition> uses;
+
+        protected final int orderNum;
+        protected int lastTo;
+
+        public Interval(int orderNum, String name, String description, String variable, String type) {
+            this.orderNum = orderNum;
+            this.name = name;
+            this.description = description;
+            this.variable = variable;
+            this.type = type;
+            this.ranges = new ArrayList<>();
+            this.uses = new ArrayList<>();
+        }
+    }
+
+
+    private final LIR lir;
+    private final RiRegisterConfig registerConfig;
+    private final DataFlowAnalysis dataFlow;
+    private final LocationMap[] blockEndLocations;
+    private final Variable[] variables;
+    private final Map<String, Interval> intervals;
+
+    private IntervalPrinter(LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow, LocationMap[] blockEndLocations) {
+        this.lir = lir;
+        this.registerConfig = registerConfig;
+        this.dataFlow = dataFlow;
+        this.blockEndLocations = blockEndLocations;
+        this.variables = new Variable[lir.numVariables()];
+        this.intervals = new HashMap<>();
+    }
+
+    private boolean isAllocatableRegister(CiValue value) {
+        return isRegister(value) && registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
+    }
+
+    private int curOpId;
+    private String curUseKind;
+
+    public Interval[] execute() {
+        ValueProcedure varProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return var(value); } };
+
+        for (Block block : lir.linearScanOrder()) {
+            for (LIRInstruction op : block.lir) {
+                op.forEachOutput(varProc);
+            }
+        }
+
+        ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
+        ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, flags); } };
+
+        intervals.put("call", new Interval(-2, "call", "", "call", "hasCall"));
+        intervals.put("st", new Interval(-1, "st", "", "st", "hasState"));
+
+        for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) {
+            Block block = lir.linearScanOrder().get(i);
+
+            curOpId = block.getLastLirInstructionId() + 2;
+            for (Block sux : block.getSuccessors()) {
+                BitSet suxIn = dataFlow.liveIn(sux);
+                for (int idx = suxIn.nextSetBit(0); idx >= 0; idx = suxIn.nextSetBit(idx + 1)) {
+                    if (blockEndLocations != null) {
+                        out(blockEndLocations[block.getId()].get(variables[idx]));
+                    } else {
+                        out(variables[idx]);
+                    }
+                }
+            }
+
+            for (int j = block.lir.size() - 1; j >= 0; j--) {
+                LIRInstruction op = block.lir.get(j);
+                if (op.id() >= 0) {
+                    curOpId = op.id();
+                } else {
+                    curOpId = (curOpId - 1) | 1;
+                }
+
+                op.forEachOutput(defProc);
+                op.forEachTemp(defProc);
+                op.forEachInput(useProc);
+                op.forEachAlive(useProc);
+                curUseKind = "L";
+                op.forEachState(useProc);
+                curUseKind = null;
+
+                if (op.hasCall()) {
+                    intervals.get("call").ranges.add(new Range(curOpId, curOpId + 1));
+                }
+                if (op.info != null) {
+                    intervals.get("st").ranges.add(new Range(curOpId, curOpId + 1));
+                }
+            }
+
+            for (Interval interval : intervals.values()) {
+                if (interval.lastTo != 0) {
+                    interval.ranges.add(new Range(block.getFirstLirInstructionId(), interval.lastTo));
+                    interval.lastTo = 0;
+                }
+            }
+        }
+
+        Interval[] intervalsArray = intervals.values().toArray(new Interval[0]);
+        Arrays.sort(intervalsArray, new Comparator<Interval>() {
+            @Override
+            public int compare(Interval o1, Interval o2) {
+                return o1.orderNum - o2.orderNum;
+            }
+        });
+        return intervalsArray;
+    }
+
+    public CiValue var(CiValue value) {
+        if (isLocation(value)) {
+            variables[asLocation(value).variable.index] = asLocation(value).variable;
+        } else if (isVariable(value)) {
+            variables[asVariable(value).index] = asVariable(value);
+        }
+        return value;
+    }
+
+    private Interval findInterval(CiValue value) {
+        Interval interval;
+        if (isLocation(value)) {
+            Interval parent = findInterval(asLocation(value).variable);
+            String name = "v" + asLocation(value).variable.index + ":" + asLocation(value).location;
+            String description = isStackSlot(asLocation(value).location) ? "stack" : "";
+            interval = new Interval(asLocation(value).variable.index * 2 + 1001, name, description, parent.name, value.kind.javaName);
+
+        } else if (isVariable(value)) {
+            interval = new Interval(asVariable(value).index * 2 + 1000, value.toString(), "", value.toString(), value.kind.javaName);
+
+        } else if (isAllocatableRegister(value)) {
+            interval = new Interval(asRegister(value).number, asRegister(value).toString(), "", asRegister(value).toString(), "fixed");
+
+        } else {
+            return null;
+        }
+
+        Interval existing = intervals.get(interval.name);
+        if (existing != null) {
+            return existing;
+        }
+        intervals.put(interval.name, interval);
+        return interval;
+    }
+
+    private String useKind(EnumSet<OperandFlag> flags) {
+        if (curUseKind != null) {
+            return curUseKind;
+        } else if (flags.contains(OperandFlag.Stack)) {
+            return "S";
+        } else {
+            return "M";
+        }
+    }
+
+    private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        Interval interval = findInterval(value);
+        if (interval != null) {
+            if (interval.uses.size() == 0 || interval.uses.get(interval.uses.size() - 1).pos != curOpId) {
+                interval.uses.add(new UsePosition(curOpId, useKind(flags)));
+            }
+            if (interval.lastTo == 0) {
+                interval.lastTo = curOpId + (mode == OperandMode.Alive ? 1 : 0);
+            }
+        }
+        return value;
+    }
+
+    private CiValue def(CiValue value, EnumSet<OperandFlag> flags) {
+        Interval interval = findInterval(value);
+        if (interval != null) {
+            interval.uses.add(new UsePosition(curOpId, useKind(flags)));
+            if (interval.lastTo == 0) {
+                interval.ranges.add(new Range(curOpId, curOpId + 1));
+            } else {
+                interval.ranges.add(new Range(curOpId, interval.lastTo));
+            }
+            interval.lastTo = 0;
+        }
+        return value;
+    }
+
+    private CiValue out(CiValue value) {
+        Interval interval = findInterval(value);
+        if (interval != null) {
+            interval.lastTo = curOpId;
+        }
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/Location.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.alloc.util;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.lir.*;
+
+public class Location extends CiValue {
+    private static final long serialVersionUID = -1786677729152726126L;
+
+    public final Variable variable;
+    public final CiValue location;
+
+    public Location(Variable variable, CiValue location) {
+        super(variable.kind);
+        this.variable = variable;
+        this.location = location;
+
+        assert variable.kind == location.kind;
+    }
+
+    @Override
+    public String toString() {
+        return variable + "[" + location + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/LocationMap.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.alloc.util;
+
+import static com.oracle.max.graal.alloc.util.LocationUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.LIRInstruction.*;
+
+public class LocationMap {
+    private final Location[] locations;
+
+    public LocationMap(int numVariables) {
+        locations = new Location[numVariables];
+    }
+
+    public LocationMap(LocationMap template) {
+        locations = Arrays.copyOf(template.locations, template.locations.length);
+    }
+
+    public Location get(Variable variable) {
+        assert locations[variable.index] == null || locations[variable.index].variable == variable;
+        return locations[variable.index];
+    }
+
+    public void put(Location location) {
+        locations[location.variable.index] = location;
+    }
+
+    public void clear(Variable variable) {
+        locations[variable.index] = null;
+    }
+
+    public void forEachLocation(ValueProcedure proc) {
+        for (int i = 0; i < locations.length; i++) {
+            if (locations[i] != null) {
+                CiValue newValue = proc.doValue(locations[i], null, null);
+                assert newValue == null || asLocation(newValue).variable == locations[i].variable;
+                locations[i] = (Location) newValue;
+            }
+        }
+    }
+
+    public boolean checkEmpty() {
+        for (int i = 0; i < locations.length; i++) {
+            assert locations[i] == null;
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/LocationUtil.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.alloc.util;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.lir.*;
+
+public class LocationUtil extends ValueUtil {
+
+    public static boolean isLocation(CiValue value) {
+        assert value != null;
+        return value instanceof Location;
+    }
+
+    public static Location asLocation(CiValue value) {
+        assert value != null;
+        return (Location) value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/MoveResolver.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.alloc.util;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+import static com.oracle.max.graal.alloc.util.LocationUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+
+public abstract class MoveResolver {
+    private final LIR lir;
+    private final FrameMap frameMap;
+    private final int[] registersBlocked;
+    private final Map<CiValue, Integer> valuesBlocked;
+    private final List<CiValue> mappingFrom;
+    private final List<Location> mappingTo;
+    private final LIRInsertionBuffer insertionBuffer;
+    private int insertPos;
+
+    public MoveResolver(LIR lir, FrameMap frameMap) {
+        this.lir = lir;
+        this.frameMap = frameMap;
+
+        registersBlocked = new int[frameMap.target.arch.registers.length];
+        valuesBlocked = new HashMap<>();
+
+        mappingFrom = new ArrayList<>();
+        mappingTo = new ArrayList<>();
+        insertionBuffer = new LIRInsertionBuffer();
+        insertPos = -1;
+
+        assert checkEmpty();
+    }
+
+    public void init(List<LIRInstruction> newInsertList, int newInsertPos) {
+        assert checkEmpty();
+
+        if (insertionBuffer.lirList() != newInsertList) {
+            // Block changed, so append insertionBuffer because it is bound to a specific block
+            finish();
+            insertionBuffer.init(newInsertList);
+        }
+        insertPos = newInsertPos;
+
+        assert checkValid();
+    }
+
+    public void add(CiValue from, Location to) {
+        assert checkValid();
+        assert isLocation(from) || isConstant(from);
+        assert from != to;
+
+        Debug.log("mr    add mapping from %s to %s", from, to);
+        mappingFrom.add(from);
+        mappingTo.add(to);
+
+        assert checkValid();
+    }
+
+    public boolean hasMappings() {
+        return mappingFrom.size() > 0;
+    }
+
+    public void resolve() {
+        assert checkValid();
+
+        if (mappingFrom.size() == 1) {
+            // If there is only one mapping, it is trivial that this mapping is safe to resolve.
+            Debug.log("mr    resolve  mappings: %d", mappingFrom.size());
+            insertMove(mappingFrom.get(0), mappingTo.get(0));
+            mappingFrom.remove(0);
+            mappingTo.remove(0);
+        } else if (mappingFrom.size() > 1) {
+            Debug.log("mr    resolve  mappings: %d", mappingFrom.size());
+            doResolve();
+        }
+        insertPos = -1;
+
+        assert checkEmpty();
+    }
+
+    public void finish() {
+        assert checkEmpty();
+
+        if (insertionBuffer.initialized()) {
+            insertionBuffer.finish();
+        }
+
+        assert !insertionBuffer.initialized() : "must be uninitialized now";
+        assert checkEmpty();
+    }
+
+
+    private void doResolve() {
+        // Block all registers and stack slots that are used as inputs of a move.
+        // When a register is blocked, no move to this register is emitted.
+        // This is necessary for detecting cycles in moves.
+        for (CiValue from : mappingFrom) {
+            block(from);
+        }
+
+        while (mappingFrom.size() > 0) {
+            boolean processed = false;
+            for (int i = mappingFrom.size() - 1; i >= 0; i--) {
+                CiValue from = mappingFrom.get(i);
+                Location to = mappingTo.get(i);
+
+                if (safeToProcessMove(from, to)) {
+                    insertMove(from, to);
+                    unblock(from);
+                    mappingFrom.remove(i);
+                    mappingTo.remove(i);
+                    processed = true;
+                }
+            }
+
+            if (!processed) {
+                // No move could be processed because there is a cycle in the move list
+                // (e.g., r1 -> r2, r2 -> r1), so one location must be spilled.
+                spill();
+            }
+        }
+    }
+
+    private void spill() {
+        Location spillCandidate = null;
+        int exchangeCandidate = -1;
+        int exchangeOther = -1;
+
+        for (int i = mappingFrom.size() - 1; i >= 0; i--) {
+            CiValue from = mappingFrom.get(i);
+            Location to = mappingTo.get(i);
+            assert !safeToProcessMove(from, to) : "would not be in this code otherwise";
+
+            if (isConstant(from)) {
+                continue;
+            }
+            CiValue fromLoc = asLocation(from).location;
+
+            // Check if we can insert an exchange to save us from spilling.
+            if (isRegister(fromLoc) && isRegister(to) && asRegister(fromLoc) != asRegister(to) && blockedCount(to) == 1) {
+                for (int j = mappingFrom.size() - 1; j >= 0; j--) {
+                    CiValue possibleOther = mappingFrom.get(j);
+                    if (isLocation(possibleOther)) {
+                        if (asLocation(possibleOther).location == to.location) {
+                            assert exchangeCandidate == -1 : "must not find twice because of blocked check above";
+                            exchangeCandidate = i;
+                            exchangeOther = j;
+                        } else if (i != j && asLocation(possibleOther).location == fromLoc) {
+                            // From is read multiple times, so exchange would be too complicated.
+                            exchangeCandidate = -1;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (exchangeCandidate != -1) {
+                // Already found a result, no need to search further
+                break;
+            }
+            if (spillCandidate == null || isStackSlot(spillCandidate.location)) {
+                // this interval cannot be processed now because target is not free
+                spillCandidate = asLocation(from);
+            }
+        }
+
+        if (exchangeCandidate != -1) {
+            Location from = asLocation(mappingFrom.get(exchangeCandidate));
+            Location to = mappingTo.get(exchangeCandidate);
+            Location other = asLocation(mappingFrom.get(exchangeOther));
+
+            Location newOther = new Location(other.variable, from.variable);
+            mappingFrom.set(exchangeOther, newOther);
+
+            insertExchange(newOther, to);
+            unblock(to);
+            mappingFrom.remove(exchangeCandidate);
+            mappingTo.remove(exchangeCandidate);
+
+        } else {
+            assert spillCandidate != null : "no location for spilling found";
+
+            Location spillLocation = new Location(spillCandidate.variable, frameMap.allocateSpillSlot(spillCandidate.kind));
+            insertMove(spillCandidate, spillLocation);
+
+            for (int i = mappingFrom.size() - 1; i >= 0; i--) {
+                if (mappingFrom.get(i) == spillCandidate) {
+                    mappingFrom.set(i, spillLocation);
+                    unblock(spillCandidate);
+                    block(spillLocation);
+                }
+            }
+            assert blockedCount(spillCandidate) == 0 : "register must be unblocked after spilling";
+        }
+    }
+
+    private void block(CiValue value) {
+        if (isLocation(value)) {
+            CiValue location = asLocation(value).location;
+            if (isRegister(location)) {
+                registersBlocked[asRegister(location).number]++;
+            } else {
+                Integer count = valuesBlocked.get(location);
+                valuesBlocked.put(location, count == null ? 1 : count + 1);
+            }
+        }
+    }
+
+    private void unblock(CiValue value) {
+        if (isLocation(value)) {
+            assert blockedCount(asLocation(value)) > 0;
+            CiValue location = asLocation(value).location;
+            if (isRegister(location)) {
+                registersBlocked[asRegister(location).number]--;
+            } else {
+                Integer count = valuesBlocked.remove(location);
+                if (count > 1) {
+                    valuesBlocked.put(location, count - 1);
+                }
+            }
+        }
+    }
+
+    private int blockedCount(Location value) {
+        CiValue location = asLocation(value).location;
+        if (isRegister(location)) {
+            return registersBlocked[asRegister(location).number];
+        } else {
+            Integer count = valuesBlocked.get(location);
+            return count == null ? 0 : count;
+        }
+    }
+
+    private boolean safeToProcessMove(CiValue from, Location to) {
+        int count = blockedCount(to);
+        return count == 0 || (count == 1 && isLocation(from) && asLocation(from).location == to.location);
+    }
+
+    private void insertExchange(Location from, Location to) {
+        Debug.log("mr      XCHG %s, %s", from, to);
+        // TODO create XCHG instruction and use it here
+        insertionBuffer.append(insertPos, null);
+        throw GraalInternalError.unimplemented();
+    }
+
+    private void insertMove(CiValue src, Location dst) {
+        if (isStackSlot(dst.location) && isLocation(src) && isStackSlot(asLocation(src).location)) {
+            // Move between two stack slots. We need a temporary registers. If the allocator can give
+            // us a free register, we need two moves: src->scratch, scratch->dst
+            // If the allocator cannot give us a free register (it returns a Location in this case),
+            // we need to spill the scratch register first, so we need four moves in total.
+
+            CiValue scratch = scratchRegister(dst.variable);
+
+            Location scratchSaved = null;
+            CiValue scratchRegister = scratch;
+            if (isLocation(scratch)) {
+                scratchSaved = new Location(asLocation(scratch).variable, frameMap.allocateSpillSlot(scratch.kind));
+                insertMove(scratch, scratchSaved);
+                scratchRegister = asLocation(scratch).location;
+            }
+            assert isRegister(scratchRegister);
+
+            Location scratchLocation = new Location(dst.variable, scratchRegister);
+            insertMove(src, scratchLocation);
+            insertMove(scratchLocation, dst);
+
+            if (scratchSaved != null) {
+                insertMove(scratchSaved, asLocation(scratch));
+            }
+
+        } else {
+            Debug.log("mr      MOV %s -> %s", src, dst);
+            insertionBuffer.append(insertPos, lir.spillMoveFactory.createMove(dst,  src));
+        }
+    }
+
+    /**
+     * Provides a register that can be used by the move resolver. If the returned value is a
+     * {@link CiRegisterValue}, the register can be overwritten without precautions. If the
+     * returned value is a {@link Location}, it needs to be spilled and rescued itself.
+     */
+    protected abstract CiValue scratchRegister(Variable spilled);
+
+    private boolean checkEmpty() {
+        assert insertPos == -1;
+        assert mappingFrom.size() == 0 && mappingTo.size() == 0;
+        for (int registerBlocked : registersBlocked) {
+            assert registerBlocked == 0;
+        }
+        assert valuesBlocked.size() == 0;
+        return true;
+    }
+
+    private boolean checkValid() {
+        assert insertPos != -1;
+        for (int registerBlocked : registersBlocked) {
+            assert registerBlocked == 0;
+        }
+        assert mappingFrom.size() == mappingTo.size();
+        assert insertionBuffer.initialized() && insertPos != -1;
+
+        for (int i = 0; i < mappingTo.size(); i++) {
+            CiValue from = mappingFrom.get(i);
+            Location to = mappingTo.get(i);
+
+            assert from.kind.stackKind() == to.kind;
+
+            for (int j = i + 1; j < mappingTo.size(); j++) {
+                Location otherTo = mappingTo.get(j);
+                assert to != otherTo && to.variable != otherTo.variable && to.location != otherTo.location : "Cannot write to same location twice";
+            }
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.alloc.util;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+import static com.oracle.max.graal.alloc.util.LocationUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.LIRInstruction.*;
+import com.oracle.max.graal.lir.cfg.*;
+
+public final class RegisterVerifier {
+    private final FrameMap frameMap;
+
+    /**
+     * All blocks that must be processed.
+     */
+    private final List<Block> workList;
+
+    /**
+     * Saved information of previous check.
+     * <br>
+     * State mapping: mapping from registers and stack slots ({@link CiRegister} and {@link Integer} stack slot offsets) to the
+     * value that is currently contained in there ({@link Location} for operands that were variables; {@link CiRegisterValue} or
+     * {@link CiStackSlot} for operands that used fixed registers or stack slots).
+     */
+    private final Map<Object, CiValue>[] blockStates;
+
+    private void addToWorkList(Block block) {
+        if (!workList.contains(block)) {
+            workList.add(block);
+        }
+    }
+
+    private Map<Object, CiValue> stateFor(Block block) {
+        return blockStates[block.getId()];
+    }
+
+    private void setStateFor(Block block, Map<Object, CiValue> savedState) {
+        blockStates[block.getId()] = savedState;
+    }
+
+    private static Map<Object, CiValue> copy(Map<Object, CiValue> inputState) {
+        return new HashMap<>(inputState);
+    }
+
+    public static boolean verify(LIR lir, FrameMap frameMap) {
+        RegisterVerifier verifier = new RegisterVerifier(lir, frameMap);
+        verifier.verify(lir.cfg.getStartBlock());
+        return true;
+    }
+
+    @SuppressWarnings("unchecked")
+    private RegisterVerifier(LIR lir, FrameMap frameMap) {
+        this.frameMap = frameMap;
+        this.workList = new LinkedList<>();
+        this.blockStates = new Map[lir.linearScanOrder().size()];
+    }
+
+    private Map<Object, CiValue> curInputState;
+
+    private void verify(Block startBlock) {
+        ValueProcedure useProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, flags); } };
+        ValueProcedure tempProc =   new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return temp(value); } };
+        ValueProcedure outputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return output(value); } };
+
+        curInputState = new HashMap<>();
+        setStateFor(startBlock, curInputState);
+        addToWorkList(startBlock);
+
+        Debug.log("==== start verify register allocation ====");
+        do {
+            Block block = workList.remove(0);
+
+            // Must copy state because it is modified.
+            curInputState = copy(stateFor(block));
+            Debug.log("start block %s %s", block, block.getLoop());
+            Debug.log(logCurrentState());
+
+            for (LIRInstruction op : block.lir) {
+                Debug.log("  op %d %s", op.id(), op);
+
+                op.forEachInput(useProc);
+                if (op.hasCall()) {
+                    invalidateRegisters();
+                }
+                op.forEachAlive(useProc);
+                op.forEachState(useProc);
+                op.forEachTemp(tempProc);
+                op.forEachOutput(outputProc);
+            }
+
+            for (Block succ : block.getSuccessors()) {
+                processSuccessor(succ);
+            }
+
+            Debug.log("end block %s", block);
+        } while (!workList.isEmpty());
+        Debug.log("==== end verify register allocation ====");
+    }
+
+    private void processSuccessor(Block succ) {
+        Map<Object, CiValue> savedState = stateFor(succ);
+        if (savedState == null) {
+            // Block was not processed before, so set initial inputState.
+            Debug.log("  successor %s: initial visit", succ);
+            setStateFor(succ, copy(curInputState));
+            addToWorkList(succ);
+
+        } else {
+            // This block was already processed before.
+            // Check if new inputState is consistent with savedState.
+            Debug.log("  successor %s: state present", succ);
+            Iterator<Map.Entry<Object, CiValue>> iter = savedState.entrySet().iterator();
+            while (iter.hasNext()) {
+                Map.Entry<Object, CiValue> entry = iter.next();
+                CiValue savedValue = entry.getValue();
+                CiValue inputValue = curInputState.get(entry.getKey());
+
+                if (savedValue != inputValue) {
+                    // Current inputState and previous savedState assume a different value in this register.
+                    // Assume that this register is invalid and remove it from the saved state.
+                    Debug.log("    invalididating %s because it is inconsistent with %s", savedValue, inputValue);
+                    iter.remove();
+                    // Must re-visit this block.
+                    addToWorkList(succ);
+                }
+            }
+        }
+    }
+
+    private void invalidateRegisters() {
+        // Invalidate all caller save registers at calls.
+        Iterator<Object> iter = curInputState.keySet().iterator();
+        while (iter.hasNext()) {
+            Object value1 = iter.next();
+            if (value1 instanceof CiRegister && frameMap.registerConfig.getAttributesMap()[((CiRegister) value1).number].isCallerSave) {
+                Debug.log("    remove caller save register %s", value1);
+                iter.remove();
+            }
+        }
+    }
+
+    /**
+     * Gets the mapping key for a value. The key should be as narrow as possible, e.g., it should not
+     * include the kind of the value because we do not want to distinguish between the same register with
+     * different kinds.
+     */
+    private Object key(CiValue value) {
+        if (isLocation(value)) {
+            return key(asLocation(value).location);
+        } else if (isRegister(value)) {
+            return asRegister(value);
+        } else if (isStackSlot(value)) {
+            return Integer.valueOf(frameMap.offsetForStackSlot(asStackSlot(value)));
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private boolean isIgnoredRegister(CiValue value) {
+        return isRegister(value) && !frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
+    }
+
+    private CiValue use(CiValue value, EnumSet<OperandFlag> flags) {
+        if (!isConstant(value) && value != CiValue.IllegalValue && !isIgnoredRegister(value)) {
+            CiValue actual = curInputState.get(key(value));
+            if (actual == null && flags.contains(OperandFlag.Uninitialized)) {
+                // OK, since uninitialized values are allowed explicitly.
+            } else if (value != actual) {
+                Debug.log("Error in register allocation: %s != %s for key %s", value, actual, key(value));
+                Debug.log(logCurrentState());
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+        return value;
+    }
+
+    private CiValue temp(CiValue value) {
+        if (!isConstant(value) && value != CiValue.IllegalValue && !isIgnoredRegister(value)) {
+            Debug.log("    temp %s -> remove key %s", value, key(value));
+            curInputState.remove(key(value));
+        }
+        return value;
+    }
+
+    private CiValue output(CiValue value) {
+        if (value != CiValue.IllegalValue && !isIgnoredRegister(value)) {
+            Debug.log("    output %s -> set key %s", value, key(value));
+            curInputState.put(key(value), value);
+        }
+        return value;
+    }
+
+
+    private String logCurrentState() {
+        ArrayList<Object> keys = new ArrayList<>(curInputState.keySet());
+        Collections.sort(keys, new Comparator<Object>() {
+            @Override
+            public int compare(Object o1, Object o2) {
+                if (o1 instanceof CiRegister) {
+                    if (o2 instanceof CiRegister) {
+                        return ((CiRegister) o1).number - ((CiRegister) o2).number;
+                    } else {
+                        return -1;
+                    }
+                } else {
+                    if (o2 instanceof CiRegister) {
+                        return 1;
+                    } else {
+                        return ((Integer) o1).intValue() - ((Integer) o2).intValue();
+                    }
+                }
+            }
+        });
+
+        StringBuilder sb = new StringBuilder("    state: ");
+        for (Object key : keys) {
+            sb.append(key).append("=").append(curInputState.get(key)).append(" ");
+        }
+        return sb.toString();
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.alloc.simple;
-
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.alloc.util.*;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-
-public abstract class AssignRegisters {
-    public final LIR lir;
-    public final FrameMap frameMap;
-
-    public AssignRegisters(LIR lir, FrameMap frameMap) {
-        this.lir = lir;
-        this.frameMap = frameMap;
-    }
-
-    private CiBitMap curRegisterRefMap;
-    private CiBitMap curFrameRefMap;
-
-    public void execute() {
-        ValueProcedure useProc =          new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value); } };
-        ValueProcedure defProc =          new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value); } };
-        ValueProcedure setReferenceProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return setReference(value); } };
-
-        assert trace("==== start assign registers ====");
-        for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) {
-            Block block = lir.linearScanOrder().get(i);
-            assert trace("start block %s", block);
-            assert block.phis == null : "Register assignment must run after phi functions have been replaced by moves";
-
-            curRegisterRefMap = frameMap.initRegisterRefMap();
-            curFrameRefMap = frameMap.initFrameRefMap();
-
-            // Put all values live at the end of the block into the reference map.
-            locationsForBlockEnd(block).forEachLocation(setReferenceProc);
-
-            for (int j = block.lir.size() - 1; j >= 0; j--) {
-                LIRInstruction op = block.lir.get(j);
-                assert trace("  op %d %s", op.id(), op);
-
-                op.forEachOutput(defProc);
-                op.forEachTemp(defProc);
-                op.forEachState(useProc);
-                op.forEachAlive(useProc);
-
-                if (op.info != null) {
-                    assert trace("    registerRefMap: %s  frameRefMap: %s", curRegisterRefMap, curFrameRefMap);
-                    op.info.finish(new CiBitMap(curRegisterRefMap), new CiBitMap(curFrameRefMap), frameMap);
-
-                    if (op instanceof LIRXirInstruction) {
-                        LIRXirInstruction xir = (LIRXirInstruction) op;
-                        if (xir.infoAfter != null) {
-                            xir.infoAfter.finish(new CiBitMap(curRegisterRefMap), new CiBitMap(curFrameRefMap), frameMap);
-                        }
-                    }
-                }
-
-                // Process input operands after assigning the reference map, so that input operands that are used
-                // for the last time at this instruction are not part of the reference map.
-                op.forEachInput(useProc);
-            }
-            assert trace("end block %s", block);
-        }
-        assert trace("==== end assign registers ====");
-    }
-
-    private CiValue use(CiValue value) {
-        assert trace("    use %s", value);
-        if (isLocation(value)) {
-            CiValue location = asLocation(value).location;
-            frameMap.setReference(location, curRegisterRefMap, curFrameRefMap);
-            return location;
-        } else {
-            frameMap.setReference(value, curRegisterRefMap, curFrameRefMap);
-            return value;
-        }
-    }
-
-    private CiValue def(CiValue value) {
-        assert trace("    def %s", value);
-        if (isLocation(value)) {
-            CiValue location = asLocation(value).location;
-            frameMap.clearReference(location, curRegisterRefMap, curFrameRefMap);
-            return location;
-        } else {
-            frameMap.clearReference(value, curRegisterRefMap, curFrameRefMap);
-            return value;
-        }
-    }
-
-    private CiValue setReference(CiValue value) {
-        assert trace("    setReference %s", value);
-        frameMap.setReference(asLocation(value).location, curRegisterRefMap, curFrameRefMap);
-        return value;
-    }
-
-    protected abstract LocationMap locationsForBlockEnd(Block block);
-
-    private static boolean trace(String format, Object...args) {
-        if (GraalOptions.TraceRegisterAllocation) {
-            TTY.println(format, args);
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,330 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.alloc.simple;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.alloc.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
-
-public class DataFlowAnalysis {
-    private final LIR lir;
-    private final RiRegisterConfig registerConfig;
-
-    public DataFlowAnalysis(LIR lir, RiRegisterConfig registerConfig) {
-        this.lir = lir;
-        this.registerConfig = registerConfig;
-    }
-
-    public void execute() {
-        numberInstructions();
-        backwardDataFlow();
-    }
-
-
-    private List<Block> blocks() {
-        return lir.linearScanOrder();
-    }
-
-    private int numVariables() {
-        return lir.numVariables();
-    }
-
-    private boolean isAllocatableRegister(CiValue value) {
-        return isRegister(value) && registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
-    }
-
-
-    private int[] definitions;
-    private BitSet[] blockLiveIn;
-    private Block[] opIdBlock;
-    private Object[] opIdKilledValues;
-
-
-    public BitSet liveIn(Block block) {
-        return blockLiveIn[block.getId()];
-    }
-    private void setLiveIn(Block block, BitSet liveIn) {
-        blockLiveIn[block.getId()] = liveIn;
-    }
-
-    private Block blockOf(int opId) {
-        return opIdBlock[opId >> 1];
-    }
-    private void setBlockOf(int opId, Block block) {
-        opIdBlock[opId >> 1] = block;
-    }
-
-    private Object killedValues(int opId) {
-        return opIdKilledValues[opId];
-    }
-    private void setKilledValues(int opId, Object killedValues) {
-        opIdKilledValues[opId] = killedValues;
-    }
-
-    public void forEachKilled(LIRInstruction op, boolean end, ValueProcedure proc) {
-        Object entry = killedValues(op.id() + (end ? 1 : 0));
-        if (entry == null) {
-            // Nothing to do
-        } else if (entry instanceof CiValue) {
-            CiValue newValue = proc.doValue((CiValue) entry, null, null);
-            assert newValue == entry : "procedure does not allow to change values";
-        } else {
-            CiValue[] values = (CiValue[]) entry;
-            for (int i = 0; i < values.length; i++) {
-                if (values[i] != null) {
-                    CiValue newValue = proc.doValue(values[i], null, null);
-                    assert newValue == values[i] : "procedure does not allow to change values";
-                }
-            }
-        }
-    }
-
-    public int definition(Variable value) {
-        return definitions[value.index];
-    }
-
-    /**
-     * Numbers all instructions in all blocks. The numbering follows the {@linkplain ComputeLinearScanOrder linear scan order}.
-     */
-    private void numberInstructions() {
-        ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return setDef(value); } };
-
-        int numInstructions = 0;
-        for (Block block : blocks()) {
-            numInstructions += block.lir.size();
-        }
-        opIdBlock = new Block[numInstructions];
-        opIdKilledValues = new Object[numInstructions << 1];
-        definitions = new int[numVariables()];
-
-        curOpId = 0;
-        for (Block block : blocks()) {
-            if (block.phis != null) {
-                block.phis.forEachOutput(defProc);
-            }
-
-            for (LIRInstruction op : block.lir) {
-                op.setId(curOpId);
-                setBlockOf(curOpId, block);
-
-                op.forEachTemp(defProc);
-                op.forEachOutput(defProc);
-
-                curOpId += 2; // numbering of lirOps by two
-            }
-        }
-        assert curOpId == numInstructions << 1;
-    }
-
-    private CiValue setDef(CiValue value) {
-        if (isVariable(value)) {
-            assert definitions[asVariable(value).index] == 0 : "Variable defined twice";
-            definitions[asVariable(value).index] = curOpId;
-        }
-        return value;
-    }
-
-
-    private BitSet variableLive;
-    private BitSet registerLive;
-    private int curOpId;
-
-    private void backwardDataFlow() {
-        ValueProcedure inputProc =       new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return use(value, curOpId); } };
-        ValueProcedure aliveProc =       new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return use(value, curOpId + 1); } };
-        PhiValueProcedure phiInputProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, -1); } };
-        ValueProcedure tempProc =        new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return def(value, true); } };
-        ValueProcedure outputProc =      new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return def(value, false); } };
-
-        blockLiveIn = new BitSet[blocks().size()];
-        registerLive = new BitSet();
-
-        assert trace("==== start backward data flow analysis ====");
-        for (int i = blocks().size() - 1; i >= 0; i--) {
-            Block block = blocks().get(i);
-            assert trace("start block %s  loop %s", block, block.getLoop());
-
-            variableLive = new BitSet();
-            for (Block sux : block.getSuccessors()) {
-                BitSet suxLive = liveIn(sux);
-                if (suxLive != null) {
-                    assert trace("  sux %s  suxLive: %s", sux, suxLive);
-                    variableLive.or(suxLive);
-                }
-
-                if (sux.phis != null) {
-                    curOpId = block.getLastLirInstructionId();
-                    assert trace("  phis %d  variableLive: %s", curOpId, variableLive);
-                    sux.phis.forEachInput(block, phiInputProc);
-                }
-            }
-
-            assert registerLive.isEmpty() : "no fixed register must be alive before processing a block";
-
-            for (int j = block.lir.size() - 1; j >= 0; j--) {
-                LIRInstruction op = block.lir.get(j);
-                curOpId = op.id();
-                assert trace("  op %d %s  variableLive: %s  registerLive: %s", curOpId, op, variableLive, registerLive);
-
-                op.forEachOutput(outputProc);
-                op.forEachTemp(tempProc);
-                op.forEachState(aliveProc);
-                op.forEachAlive(aliveProc);
-                op.forEachInput(inputProc);
-            }
-
-            if (block.phis != null) {
-                curOpId = block.getFirstLirInstructionId();
-                assert trace("  phis %d  variableLive: %s  registerLive: %s", curOpId, variableLive, registerLive);
-                block.phis.forEachOutput(outputProc);
-            }
-
-            assert registerLive.isEmpty() : "no fixed register must be alive after processing a block";
-            assert liveIn(block) == null;
-            setLiveIn(block, variableLive);
-
-            if (block.isLoopHeader()) {
-                assert trace("  loop header, propagating live set to loop blocks  variableLive: %s", variableLive);
-                // All variables that are live at the beginning of a loop are also live the whole loop.
-                // This is guaranteed by the SSA form.
-                for (Block loop : block.getLoop().blocks) {
-                    BitSet loopLiveIn = liveIn(loop);
-                    assert loopLiveIn != null : "All loop blocks must have been processed before the loop header";
-                    loopLiveIn.or(variableLive);
-                    assert trace("    block %s  loopLiveIn %s", loop, loopLiveIn);
-                }
-            }
-
-            assert trace("end block %s  variableLive: %s", block, variableLive);
-        }
-        assert trace("==== end backward data flow analysis ====");
-    }
-
-    private CiValue use(CiValue value, int killOpId) {
-        assert trace("    use %s", value);
-        if (isVariable(value)) {
-            int variableIdx = asVariable(value).index;
-            assert definitions[variableIdx] < curOpId;
-            if (!variableLive.get(variableIdx)) {
-                assert trace("      set live variable %d", variableIdx);
-                variableLive.set(variableIdx);
-                kill(value, killOpId);
-            }
-
-        } else if (isAllocatableRegister(value)) {
-            int regNum = asRegister(value).number;
-            if (!registerLive.get(regNum)) {
-                assert trace("      set live register %d", regNum);
-                registerLive.set(regNum);
-                kill(value, killOpId);
-            }
-        }
-        return value;
-    }
-
-    private CiValue def(CiValue value, boolean isTemp) {
-        assert trace("    def %s", value);
-        if (isVariable(value)) {
-            int variableIdx = asVariable(value).index;
-            assert definitions[variableIdx] == curOpId;
-            if (variableLive.get(variableIdx)) {
-                assert trace("      clear live variable %d", variableIdx);
-                assert !isTemp : "temp variable cannot be used after the operation";
-                variableLive.clear(variableIdx);
-            } else {
-                // Variable has never been used, so kill it immediately after the definition.
-                kill(value, curOpId + 1);
-            }
-
-        } else if (isAllocatableRegister(value)) {
-            int regNum = asRegister(value).number;
-            if (registerLive.get(regNum)) {
-                assert trace("      clear live register %d", regNum);
-                assert !isTemp : "temp variable cannot be used after the operation";
-                registerLive.clear(regNum);
-            } else {
-                // Register has never been used, so kill it immediately after the definition.
-                kill(value, curOpId + 1);
-            }
-        }
-        return value;
-    }
-
-    private void kill(CiValue value, int opId) {
-        if (opId < 0) {
-            return;
-        }
-        if (isVariable(value)) {
-            int defOpId = definitions[asVariable(value).index];
-            assert defOpId > 0 && defOpId <= opId;
-
-            Block defBlock = blockOf(defOpId);
-            Block useBlock = blockOf(opId);
-
-            if (useBlock.getLoop() != null && useBlock.getLoop() != defBlock.getLoop()) {
-                // This is a value defined outside of the loop it is currently used in.  Therefore, it is live the whole loop
-                // and is not killed by the current instruction.
-                assert trace("      no kill because use in %s, definition in %s", useBlock.getLoop(), defBlock.getLoop());
-                return;
-            }
-        }
-        assert trace("      kill %s at %d", value, opId);
-
-        Object entry = killedValues(opId);
-        if (entry == null) {
-            setKilledValues(opId, value);
-        } else if (entry instanceof CiValue) {
-            setKilledValues(opId, new CiValue[] {(CiValue) entry, value});
-        } else {
-            CiValue[] killed = (CiValue[]) entry;
-            for (int i = 0; i < killed.length; i++) {
-                if (killed[i] == null) {
-                    killed[i] = value;
-                    return;
-                }
-            }
-            int oldLen = killed.length;
-            killed = Arrays.copyOf(killed, oldLen * 2);
-            setKilledValues(opId, killed);
-            killed[oldLen] = value;
-        }
-    }
-
-    private static boolean trace(String format, Object...args) {
-        if (GraalOptions.TraceRegisterAllocation) {
-            TTY.println(format, args);
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,604 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.alloc.simple;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ci.CiRegister.RegisterFlag;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.alloc.util.*;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.debug.*;
-
-public class LinearScanAllocator {
-    private final LIR lir;
-    private final FrameMap frameMap;
-
-    private final DataFlowAnalysis dataFlow;
-
-    public LinearScanAllocator(LIR lir, FrameMap frameMap) {
-        this.lir = lir;
-        this.frameMap = frameMap;
-
-        this.dataFlow = new DataFlowAnalysis(lir, frameMap.registerConfig);
-        this.blockBeginLocations = new LocationMap[lir.linearScanOrder().size()];
-        this.blockEndLocations = new LocationMap[lir.linearScanOrder().size()];
-        this.moveResolver = new MoveResolverImpl(lir, frameMap);
-
-        this.variableLastUse = new int[lir.numVariables()];
-    }
-
-    private class MoveResolverImpl extends MoveResolver {
-        public MoveResolverImpl(LIR lir, FrameMap frameMap) {
-            super(lir, frameMap);
-        }
-
-        @Override
-        protected CiValue scratchRegister(Variable spilled) {
-            Util.shouldNotReachHere("needs working implementation");
-
-            EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters();
-            CiRegister[] availableRegs = categorizedRegs.get(spilled.flag);
-            for (CiRegister reg : availableRegs) {
-                if (curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null) {
-                    return reg.asValue(spilled.kind);
-                }
-            }
-            throw new CiBailout("No register found");
-        }
-    }
-
-    private class ResolveDataFlowImpl extends ResolveDataFlow {
-        public ResolveDataFlowImpl(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) {
-            super(lir, moveResolver, dataFlow);
-        }
-
-        @Override
-        protected LocationMap locationsForBlockBegin(Block block) {
-            return beginLocationsFor(block);
-        }
-
-        @Override
-        protected LocationMap locationsForBlockEnd(Block block) {
-            return endLocationsFor(block);
-        }
-    }
-
-    private class AssignRegistersImpl extends AssignRegisters {
-        public AssignRegistersImpl(LIR lir, FrameMap frameMap) {
-            super(lir, frameMap);
-        }
-
-        @Override
-        protected LocationMap locationsForBlockEnd(Block block) {
-            return endLocationsFor(block);
-        }
-    }
-
-
-    private int maxRegisterNum() {
-        return frameMap.target.arch.registers.length;
-    }
-
-    private boolean isAllocatableRegister(CiValue value) {
-        return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
-    }
-
-
-    private final LocationMap[] blockBeginLocations;
-
-    private LocationMap beginLocationsFor(Block block) {
-        return blockBeginLocations[block.getId()];
-    }
-    private void setBeginLocationsFor(Block block, LocationMap locations) {
-        blockBeginLocations[block.getId()] = locations;
-    }
-
-    private final LocationMap[] blockEndLocations;
-
-    private LocationMap endLocationsFor(Block block) {
-        return blockEndLocations[block.getId()];
-    }
-    private void setEndLocationsFor(Block block, LocationMap locations) {
-        blockEndLocations[block.getId()] = locations;
-    }
-
-    private final int[] variableLastUse;
-
-    private int lastUseFor(Variable variable) {
-        return variableLastUse[variable.index];
-    }
-
-    private void setLastUseFor(Variable variable, int lastUse) {
-        variableLastUse[variable.index] = lastUse;
-    }
-
-    private MoveResolver moveResolver;
-    private LocationMap curLocations;
-    private CiValue[] curInRegisterState;
-    private CiValue[] curOutRegisterState;
-    private BitSet curLiveIn;
-    private int curOpId;
-    private Block curPhiBlock;
-
-    private LocationMap canonicalSpillLocations;
-
-    public void execute() {
-        assert LIRVerifier.verify(true, lir, frameMap);
-
-        dataFlow.execute();
-        IntervalPrinter.printBeforeAllocation("Before register allocation", lir, frameMap.registerConfig, dataFlow);
-
-        allocate();
-
-        IntervalPrinter.printAfterAllocation("After linear scan allocation", lir, frameMap.registerConfig, dataFlow, blockEndLocations);
-
-        ResolveDataFlow resolveDataFlow = new ResolveDataFlowImpl(lir, moveResolver, dataFlow);
-        resolveDataFlow.execute();
-        frameMap.finish();
-
-        IntervalPrinter.printAfterAllocation("After resolve data flow", lir, frameMap.registerConfig, dataFlow, blockEndLocations);
-        assert RegisterVerifier.verify(lir, frameMap);
-
-        AssignRegisters assignRegisters = new AssignRegistersImpl(lir, frameMap);
-        assignRegisters.execute();
-
-        Debug.dump(lir, "After register asignment");
-        assert LIRVerifier.verify(false, lir, frameMap);
-    }
-
-    private void allocate() {
-        ValueProcedure recordUseProc =    new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return recordUse(value, mode); } };
-        ValueProcedure killNonLiveProc =  new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return killNonLive(value); } };
-        ValueProcedure unblockProc =      new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return unblock(value); } };
-        ValueProcedure killProc =      new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return kill(value); } };
-        ValueProcedure blockProc =        new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return block(value); } };
-        PhiValueProcedure useProc =          new PhiValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
-        ValueProcedure defProc =          new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } };
-
-        assert trace("==== start linear scan allocation ====");
-        canonicalSpillLocations = new LocationMap(lir.numVariables());
-        curInRegisterState = new CiValue[maxRegisterNum()];
-        curOutRegisterState = new CiValue[maxRegisterNum()];
-        for (Block block : lir.linearScanOrder()) {
-            assert trace("start block %s %s", block, block.getLoop());
-
-            Arrays.fill(curOutRegisterState, null);
-            if (block.getDominator() != null) {
-                LocationMap dominatorState = endLocationsFor(block.getDominator());
-                curLocations = new LocationMap(dominatorState);
-                // Clear out all variables that are not live at the begin of this block
-                curLiveIn = dataFlow.liveIn(block);
-                curLocations.forEachLocation(killNonLiveProc);
-                assert checkInputState(block);
-            } else {
-                curLocations = new LocationMap(lir.numVariables());
-            }
-            assert traceState();
-
-            if (block.phis != null) {
-                assert trace("  phis");
-                curPhiBlock = block;
-                curOpId = block.getFirstLirInstructionId();
-                block.phis.forEachOutput(defProc);
-                curOpId = -1;
-                curPhiBlock = null;
-            }
-
-            setBeginLocationsFor(block, new LocationMap(curLocations));
-
-            for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) {
-                LIRInstruction op = block.lir.get(opIdx);
-                curOpId = op.id();
-                assert trace("  op %d %s", op.id(), op);
-
-                System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length);
-
-                // Unblock fixed registers that are only used for inputs in curOutRegisterState.
-                dataFlow.forEachKilled(op, false, unblockProc);
-                // Block fixed registers defined by this instruction in curOutRegisterState.
-                op.forEachTemp(blockProc);
-                op.forEachOutput(blockProc);
-
-                op.forEachInput(recordUseProc);
-                op.forEachAlive(recordUseProc);
-
-                moveResolver.init(block.lir, opIdx);
-                // Process Alive before Input because they are more restricted and the same variable can be Alive and Input.
-                op.forEachAlive(useProc);
-                op.forEachInput(useProc);
-
-                dataFlow.forEachKilled(op, false, killProc);
-
-                if (op.hasCall()) {
-                    spillCallerSaveRegisters();
-                }
-
-                op.forEachTemp(defProc);
-                op.forEachOutput(defProc);
-
-                // Fixed temp and output registers can evict variables from their assigned register, allocate new location for them.
-                fixupEvicted();
-                // State values are the least critical and can get the leftover registers (or stack slots if no more register available).
-                op.forEachState(useProc);
-
-
-                moveResolver.resolve();
-
-                dataFlow.forEachKilled(op, true, unblockProc);
-                dataFlow.forEachKilled(op, true, killProc);
-
-//                curInstruction = null;
-                curOpId = -1;
-            }
-
-            for (Block sux : block.getSuccessors()) {
-                if (sux.phis != null) {
-                    assert trace("  phis of successor %s", sux);
-                    System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length);
-                    curOpId = block.getLastLirInstructionId() + 1;
-                    sux.phis.forEachInput(block, useProc);
-                    curOpId = -1;
-                }
-            }
-
-            assert endLocationsFor(block) == null;
-            setEndLocationsFor(block, curLocations);
-
-            traceState();
-            assert trace("end block %s", block);
-        }
-
-        moveResolver.finish();
-        assert trace("==== end linear scan allocation ====");
-    }
-
-    private CiValue killNonLive(CiValue value) {
-        assert isLocation(value);
-        if (!curLiveIn.get(asLocation(value).variable.index)) {
-            return null;
-
-        } else if (isAllocatableRegister(asLocation(value).location)) {
-            int regNum = asRegister(asLocation(value).location).number;
-            assert curOutRegisterState[regNum] == null;
-            curOutRegisterState[regNum] = value;
-        }
-        return value;
-    }
-
-    private CiValue unblock(CiValue value) {
-        if (isAllocatableRegister(value)) {
-            assert trace("    unblock register %s", value);
-            int regNum = asRegister(value).number;
-            assert curOutRegisterState[regNum] == value;
-            curOutRegisterState[regNum] = null;
-        }
-        return value;
-    }
-
-    private CiValue kill(CiValue value) {
-        if (isVariable(value)) {
-            Location location = curLocations.get(asVariable(value));
-            assert trace("    kill location %s", location);
-            if (isRegister(location.location)) {
-                int regNum = asRegister(location.location).number;
-                if (curOutRegisterState[regNum] == location) {
-                    curOutRegisterState[regNum] = null;
-                }
-            }
-            curLocations.clear(asVariable(value));
-        }
-        return value;
-    }
-
-
-    private CiValue block(CiValue value) {
-        if (isAllocatableRegister(value)) {
-            assert trace("    block %s", value);
-            int regNum = asRegister(value).number;
-            assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof Location;
-            curOutRegisterState[regNum] = value;
-        }
-        return value;
-    }
-
-    private void spillCallerSaveRegisters() {
-        assert trace("    spill caller save registers in curInRegisterState %s", Arrays.toString(curInRegisterState));
-        for (CiRegister reg : frameMap.registerConfig.getCallerSaveRegisters()) {
-            CiValue in = curInRegisterState[reg.number];
-            if (in != null && isLocation(in)) {
-                spill(asLocation(in));
-            }
-        }
-    }
-
-    private CiValue recordUse(CiValue value, OperandMode mode) {
-        if (isVariable(value)) {
-            int id = mode == OperandMode.Input ? curOpId : curOpId + 1;
-            assert lastUseFor(asVariable(value)) <= id;
-            setLastUseFor(asVariable(value), id);
-
-        }
-        return value;
-    }
-
-    private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Input || mode == OperandMode.Alive;
-        if (isVariable(value)) {
-            // State values are not recorded beforehand because it does not matter if they are spilled. Still, it is necessary to record them as used now.
-            recordUse(value, mode);
-
-            Location curLoc = curLocations.get(asVariable(value));
-            if (isStackSlot(curLoc.location) && flags.contains(OperandFlag.Stack)) {
-                assert trace("    use %s %s: use current stack slot %s", mode, value, curLoc.location);
-                return curLoc;
-            }
-            if (isRegister(curLoc.location)) {
-                int regNum = asRegister(curLoc.location).number;
-                assert curInRegisterState[regNum] == curLoc;
-                if (mode == OperandMode.Input || curOutRegisterState[regNum] == curLoc) {
-                    assert trace("    use %s %s: use current register %s", mode, value, curLoc.location);
-                    return curLoc;
-                }
-            }
-
-            assert trace("    use %s %s", mode, value);
-
-            Location newLoc = allocateRegister(asVariable(value), mode, flags);
-            if (newLoc != curLoc) {
-                moveResolver.add(curLoc, newLoc);
-            }
-            return newLoc;
-        } else {
-            assert !isAllocatableRegister(value) || curInRegisterState[asRegister(value).number] == value;
-        }
-        return value;
-    }
-
-    private static final EnumSet<OperandFlag> SPILL_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-
-    private CiValue def(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Temp || mode == OperandMode.Output;
-        if (isVariable(value)) {
-            assert trace("    def %s %s", mode, value);
-            assert curLocations.get(asVariable(value)) == null;
-
-            Location newLoc = allocateRegister(asVariable(value), mode, flags);
-            return newLoc;
-        }
-        return value;
-    }
-
-
-    private void fixupEvicted() {
-        for (int i = 0; i < curInRegisterState.length; i++) {
-            CiValue in = curInRegisterState[i];
-            CiValue out = curOutRegisterState[i];
-
-            if (in != null && in != out && isLocation(in) && curLocations.get(asLocation(in).variable) == in) {
-                assert trace("    %s was evicted by %s, need to allocate new location", in, out);
-                Location oldLoc = asLocation(in);
-                Location newLoc = allocateRegister(oldLoc.variable, OperandMode.Alive, SPILL_FLAGS);
-                assert oldLoc != newLoc;
-                moveResolver.add(oldLoc, newLoc);
-            }
-
-
-        }
-    }
-
-
-    private Location allocateRegister(final Variable variable, OperandMode mode, EnumSet<OperandFlag> flags) {
-//        if (flags.contains(OperandFlag.RegisterHint)) {
-//            CiValue result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() {
-//                @Override
-//                public CiValue doValue(CiValue registerHint) {
-//                    assert trace("      registerHint %s", registerHint);
-//                    CiRegister hint = null;
-//                    if (isRegister(registerHint)) {
-//                        hint = asRegister(registerHint);
-//                    } else if (isLocation(registerHint) && isRegister(asLocation(registerHint).location)) {
-//                        hint = asRegister(asLocation(registerHint).location);
-//                    }
-//                    if (hint != null && hint.isSet(variable.flag) && isFree(hint, inRegisterState, outRegisterState)) {
-//                        return selectRegister(hint, variable, inRegisterState, outRegisterState);
-//                    }
-//                    return null;
-//                }
-//            });
-//
-//            if (result != null) {
-//                return asLocation(result);
-//            }
-//        }
-//
-        EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters();
-        CiRegister[] availableRegs = categorizedRegs.get(variable.flag);
-
-        Location bestSpillCandidate = null;
-        for (CiRegister reg : availableRegs) {
-            if (isFree(reg, mode)) {
-                return selectRegister(reg, variable, mode);
-            } else {
-                Location spillCandidate = spillCandidate(reg);
-                if (betterSpillCandidate(spillCandidate, bestSpillCandidate)) {
-                    bestSpillCandidate = spillCandidate;
-                }
-            }
-        }
-
-        if (flags.contains(OperandFlag.Stack) && betterSpillCandidate(curLocations.get(variable), bestSpillCandidate)) {
-            return selectSpillSlot(variable, mode);
-        }
-
-        if (bestSpillCandidate == null) {
-            if (curPhiBlock != null) {
-                return selectSpillSlot(variable, mode);
-            }
-            // This should not happen as long as all LIR instructions have fulfillable register constraints. But be safe in product mode and bail out.
-            assert false;
-            throw new CiBailout("No register available");
-        }
-
-        spill(bestSpillCandidate);
-
-        return selectRegister(asRegister(bestSpillCandidate.location), variable, mode);
-    }
-
-    private void spill(Location value) {
-        Location newLoc = spillLocation(value.variable);
-        assert trace("      spill %s to %s", value, newLoc);
-        if (curPhiBlock == null) {
-            moveResolver.add(value, newLoc);
-        }
-        curLocations.put(newLoc);
-
-        CiRegister reg = asRegister(value.location);
-        assert curInRegisterState[reg.number] == value;
-        curInRegisterState[reg.number] = null;
-        if (curOutRegisterState[reg.number] == value) {
-            curOutRegisterState[reg.number] = null;
-        }
-    }
-
-    private boolean isFree(CiRegister reg, OperandMode mode) {
-        switch (mode) {
-            case Input:  return curInRegisterState[reg.number] == null;
-            case Alive:  return curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null;
-            case Temp:   return curOutRegisterState[reg.number] == null;
-            case Output: return curOutRegisterState[reg.number] == null;
-            default:     throw Util.shouldNotReachHere();
-        }
-    }
-
-    private Location spillCandidate(CiRegister reg) {
-        CiValue in = curInRegisterState[reg.number];
-        CiValue out = curOutRegisterState[reg.number];
-        if (in == out && in != null && isLocation(in) && lastUseFor(asLocation(in).variable) < curOpId) {
-            return asLocation(in);
-        }
-        return null;
-    }
-
-    private boolean betterSpillCandidate(Location loc, Location compare) {
-        if (loc == null) {
-            return false;
-        }
-        if (compare == null) {
-            return true;
-        }
-        if (canonicalSpillLocations.get(loc.variable) != null && canonicalSpillLocations.get(compare.variable) == null) {
-            return true;
-        }
-        return dataFlow.definition(loc.variable) < dataFlow.definition(compare.variable);
-    }
-
-    private Location spillLocation(Variable variable) {
-        Location result = canonicalSpillLocations.get(variable);
-        if (result == null) {
-            result = new Location(variable, frameMap.allocateSpillSlot(variable.kind));
-            canonicalSpillLocations.put(result);
-        }
-        return result;
-    }
-
-    private Location selectRegister(CiRegister reg, Variable variable, OperandMode mode) {
-        assert isFree(reg, mode);
-
-        Location loc = new Location(variable, reg.asValue(variable.kind));
-        if (mode == OperandMode.Input || mode == OperandMode.Alive) {
-            curInRegisterState[reg.number] = loc;
-        }
-        curOutRegisterState[reg.number] = loc;
-        curLocations.put(loc);
-        recordUse(variable, mode);
-
-        assert trace("      selected register %s", loc);
-        return loc;
-    }
-
-    private Location selectSpillSlot(Variable variable, OperandMode mode) {
-        Location loc = spillLocation(variable);
-        curLocations.put(loc);
-        recordUse(variable, mode);
-
-        assert trace("      selected spill slot %s", loc);
-        return loc;
-    }
-
-    private boolean checkInputState(final Block block) {
-        final BitSet liveState = new BitSet();
-        curLocations.forEachLocation(new ValueProcedure() {
-            @Override
-            public CiValue doValue(CiValue value) {
-                liveState.set(asLocation(value).variable.index);
-
-                for (Block pred : block.getPredecessors()) {
-                    LocationMap predState = endLocationsFor(pred);
-                    if (predState != null) {
-                        assert predState.get(asLocation(value).variable) != null;
-                    } else {
-                        assert block.isLoopHeader();
-                    }
-                }
-                return value;
-            }
-        });
-        assert liveState.equals(curLiveIn);
-        return true;
-    }
-
-
-    private boolean traceState() {
-        if (GraalOptions.TraceRegisterAllocation) {
-            TTY.print("  current lcoations: ");
-            curLocations.forEachLocation(new ValueProcedure() {
-                @Override
-                public CiValue doValue(CiValue value) {
-                    TTY.print("%s ", value);
-                    return value;
-                }
-            });
-            TTY.println();
-        }
-        return true;
-    }
-
-    private static boolean trace(String format, Object...args) {
-        if (GraalOptions.TraceRegisterAllocation) {
-            TTY.println(format, args);
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.alloc.simple;
-
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.alloc.util.*;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
-import com.oracle.max.graal.compiler.util.*;
-
-public abstract class ResolveDataFlow {
-    public final LIR lir;
-    public final MoveResolver moveResolver;
-    public final DataFlowAnalysis dataFlow;
-
-    public ResolveDataFlow(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) {
-        this.lir = lir;
-        this.moveResolver = moveResolver;
-        this.dataFlow = dataFlow;
-    }
-
-    private Block curToBlock;
-    private LocationMap curFromLocations;
-
-    public void execute() {
-        ValueProcedure locMappingProc =    new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return locMapping(value); } };
-        PhiValueProcedure phiMappingProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue input, CiValue output) { return phiMapping(input, output); } };
-
-        assert trace("==== start resolve data flow ====");
-        for (Block toBlock : lir.linearScanOrder()) {
-            curToBlock = toBlock;
-
-            for (Block fromBlock : toBlock.getPredecessors()) {
-                assert trace("start edge %s -> %s", fromBlock, toBlock);
-                findInsertPos(fromBlock, toBlock);
-
-                LocationMap toLocations = locationsForBlockBegin(toBlock);
-                curFromLocations = locationsForBlockEnd(fromBlock);
-                if (toLocations != curFromLocations) {
-                    toLocations.forEachLocation(locMappingProc);
-                }
-
-                if (toBlock.phis != null) {
-                    toBlock.phis.forEachInput(fromBlock, phiMappingProc);
-                }
-
-                moveResolver.resolve();
-                assert trace("end edge %s -> %s", fromBlock, toBlock);
-            }
-
-            // Phi functions are resolved with moves now, so delete them.
-            toBlock.phis = null;
-        }
-        moveResolver.finish();
-        assert trace("==== end resolve data flow ====");
-    }
-
-    private CiValue locMapping(CiValue value) {
-        Location to = asLocation(value);
-        Location from = curFromLocations.get(to.variable);
-        if (value != from && dataFlow.liveIn(curToBlock).get(to.variable.index)) {
-            moveResolver.add(from, to);
-        }
-        return value;
-    }
-
-    private CiValue phiMapping(CiValue input, CiValue output) {
-        if (input != output) {
-            moveResolver.add(input, asLocation(output));
-        }
-        return input;
-    }
-
-    private void findInsertPos(Block fromBlock, Block toBlock) {
-        assert fromBlock.getSuccessors().contains(toBlock) && toBlock.getPredecessors().contains(fromBlock);
-
-        if (fromBlock.numberOfSux() == 1) {
-            List<LIRInstruction> instructions = fromBlock.lir;
-            LIRInstruction instr = instructions.get(instructions.size() - 1);
-            assert instr instanceof StandardOp.JumpOp : "block does not end with an unconditional jump";
-            moveResolver.init(instructions, instructions.size() - 1);
-            assert trace("  insert at end of %s before %d", fromBlock, instructions.size() - 1);
-
-        } else if (toBlock.numberOfPreds() == 1) {
-            moveResolver.init(toBlock.lir, 1);
-            assert trace("  insert at beginning of %s before %d", toBlock, 1);
-
-        } else {
-            Util.shouldNotReachHere("Critical edge not split");
-        }
-    }
-
-    protected abstract LocationMap locationsForBlockBegin(Block block);
-    protected abstract LocationMap locationsForBlockEnd(Block block);
-
-
-    private static boolean trace(String format, Object...args) {
-        if (GraalOptions.TraceRegisterAllocation) {
-            TTY.println(format, args);
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,495 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.alloc.simple;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ci.CiRegister.RegisterFlag;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.alloc.util.*;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.debug.*;
-
-public class SpillAllAllocator {
-    private final LIR lir;
-    private final FrameMap frameMap;
-
-    private final DataFlowAnalysis dataFlow;
-
-    public SpillAllAllocator(LIR lir, FrameMap frameMap) {
-        this.lir = lir;
-        this.frameMap = frameMap;
-
-        this.dataFlow = new DataFlowAnalysis(lir, frameMap.registerConfig);
-        this.blockLocations = new LocationMap[lir.linearScanOrder().size()];
-        this.moveResolver = new MoveResolverImpl(lir, frameMap);
-    }
-
-    private class MoveResolverImpl extends MoveResolver {
-        public MoveResolverImpl(LIR lir, FrameMap frameMap) {
-            super(lir, frameMap);
-        }
-
-        @Override
-        protected CiValue scratchRegister(Variable spilled) {
-            EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters();
-            CiRegister[] availableRegs = categorizedRegs.get(spilled.flag);
-            for (CiRegister reg : availableRegs) {
-                if (curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null) {
-                    return reg.asValue(spilled.kind);
-                }
-            }
-            throw new CiBailout("No register found");
-        }
-    }
-
-    private class ResolveDataFlowImpl extends ResolveDataFlow {
-        public ResolveDataFlowImpl(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) {
-            super(lir, moveResolver, dataFlow);
-        }
-
-        @Override
-        protected LocationMap locationsForBlockBegin(Block block) {
-            assert block.numberOfPreds() > 0 && block.getDominator() != null;
-            return locationsFor(block.getDominator());
-        }
-
-        @Override
-        protected LocationMap locationsForBlockEnd(Block block) {
-            return locationsFor(block);
-        }
-    }
-
-    private class AssignRegistersImpl extends AssignRegisters {
-        public AssignRegistersImpl(LIR lir, FrameMap frameMap) {
-            super(lir, frameMap);
-        }
-
-        @Override
-        protected LocationMap locationsForBlockEnd(Block block) {
-            return locationsFor(block);
-        }
-    }
-
-
-    private int maxRegisterNum() {
-        return frameMap.target.arch.registers.length;
-    }
-
-    private boolean isAllocatableRegister(CiValue value) {
-        return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
-    }
-
-
-    private final LocationMap[] blockLocations;
-
-    private LocationMap locationsFor(Block block) {
-        return blockLocations[block.getId()];
-    }
-    private void setLocationsFor(Block block, LocationMap locations) {
-        blockLocations[block.getId()] = locations;
-    }
-
-    private MoveResolver moveResolver;
-    private LocationMap curStackLocations;
-    private LocationMap curRegisterLocations;
-    private Object[] curInRegisterState;
-    private Object[] curOutRegisterState;
-    private BitSet curLiveIn;
-    private LIRInstruction curInstruction;
-
-    public void execute() {
-        assert LIRVerifier.verify(true, lir, frameMap);
-
-        dataFlow.execute();
-        IntervalPrinter.printBeforeAllocation("Before register allocation", lir, frameMap.registerConfig, dataFlow);
-
-        allocate();
-
-        IntervalPrinter.printAfterAllocation("After spill all allocation", lir, frameMap.registerConfig, dataFlow, blockLocations);
-
-        ResolveDataFlow resolveDataFlow = new ResolveDataFlowImpl(lir, moveResolver, dataFlow);
-        resolveDataFlow.execute();
-        frameMap.finish();
-
-        IntervalPrinter.printAfterAllocation("After resolve data flow", lir, frameMap.registerConfig, dataFlow, blockLocations);
-        assert RegisterVerifier.verify(lir, frameMap);
-
-        AssignRegisters assignRegisters = new AssignRegistersImpl(lir, frameMap);
-        assignRegisters.execute();
-
-        Debug.dump(lir, "After register asignment");
-        assert LIRVerifier.verify(false, lir, frameMap);
-    }
-
-    private void allocate() {
-        ValueProcedure killNonLiveProc =  new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return killNonLive(value); } };
-        ValueProcedure killBeginProc =    new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return kill(value, false); } };
-        ValueProcedure killEndProc =      new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return kill(value, true); } };
-        ValueProcedure killLocationProc = new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return killLocation(value); } };
-        ValueProcedure blockProc =        new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return block(value); } };
-        ValueProcedure loadProc =         new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return load(value, mode, flags); } };
-        ValueProcedure spillProc =        new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return spill(value, mode, flags); } };
-        PhiValueProcedure useSlotProc =   new PhiValueProcedure() { @Override public CiValue doValue(CiValue value) { return useSlot(value); } };
-        ValueProcedure defSlotProc =      new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return defSlot(value); } };
-
-        assert trace("==== start spill all allocation ====");
-        curInRegisterState = new Object[maxRegisterNum()];
-        curOutRegisterState = new Object[maxRegisterNum()];
-        curRegisterLocations = new LocationMap(lir.numVariables());
-        for (Block block : lir.linearScanOrder()) {
-            assert trace("start block %s %s", block, block.getLoop());
-            assert checkEmpty(curOutRegisterState);
-
-            if (block.getDominator() != null) {
-                LocationMap dominatorState = locationsFor(block.getDominator());
-                curStackLocations = new LocationMap(dominatorState);
-                // Clear out all variables that are not live at the begin of this block
-                curLiveIn = dataFlow.liveIn(block);
-                curStackLocations.forEachLocation(killNonLiveProc);
-                assert checkInputState(block);
-            } else {
-                curStackLocations = new LocationMap(lir.numVariables());
-            }
-            assert traceState();
-
-            if (block.phis != null) {
-                assert trace("  phis");
-                block.phis.forEachOutput(defSlotProc);
-            }
-
-            for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) {
-                LIRInstruction op = block.lir.get(opIdx);
-                curInstruction = op;
-                assert trace("  op %d %s", op.id(), op);
-
-                assert curRegisterLocations.checkEmpty();
-
-                System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length);
-
-                // Block fixed registers that are defined by this instruction, so that they are no longer available for normal allocation.
-                op.forEachTemp(blockProc);
-                op.forEachOutput(blockProc);
-
-                moveResolver.init(block.lir, opIdx);
-                // Process Alive before Input because they are more restricted and the same variable can be Alive and Input.
-                op.forEachAlive(loadProc);
-                op.forEachInput(loadProc);
-                moveResolver.resolve();
-                op.forEachState(useSlotProc);
-
-                dataFlow.forEachKilled(op, false, killBeginProc);
-                assert !op.hasCall() || checkNoCallerSavedRegister() : "caller saved register in use accross call site";
-
-                moveResolver.init(block.lir, opIdx + 1);
-                op.forEachTemp(spillProc);
-                op.forEachOutput(spillProc);
-                moveResolver.resolve();
-
-                dataFlow.forEachKilled(op, true, killEndProc);
-                curRegisterLocations.forEachLocation(killLocationProc);
-
-                assert curRegisterLocations.checkEmpty();
-                curInstruction = null;
-            }
-            assert checkEmpty(curOutRegisterState);
-
-            for (Block sux : block.getSuccessors()) {
-                if (sux.phis != null) {
-                    assert trace("  phis of successor %s", sux);
-                    sux.phis.forEachInput(block, useSlotProc);
-                }
-            }
-
-            assert checkEmpty(curOutRegisterState);
-            assert locationsFor(block) == null;
-            setLocationsFor(block, curStackLocations);
-
-            traceState();
-            assert trace("end block %s", block);
-        }
-
-        moveResolver.finish();
-        assert trace("==== end spill all allocation ====");
-    }
-
-    private CiValue killNonLive(CiValue value) {
-        assert isLocation(value);
-        if (!curLiveIn.get(asLocation(value).variable.index)) {
-            return null;
-        }
-        return value;
-    }
-
-    private CiValue kill(CiValue value, boolean end) {
-        if (isVariable(value)) {
-            assert trace("    kill variable %s", value);
-
-            Variable variable = asVariable(value);
-            curStackLocations.clear(variable);
-
-            Location loc = curRegisterLocations.get(variable);
-            if (loc != null) {
-                killLocation(loc);
-                curRegisterLocations.clear(variable);
-
-                assert trace("      location %s", loc);
-                assert isAllocatableRegister(loc.location);
-
-                int regNum = asRegister(loc.location).number;
-                if (curOutRegisterState[regNum] == loc) {
-                    curOutRegisterState[regNum] = null;
-                }
-            }
-
-        } else if (isAllocatableRegister(value)) {
-            assert trace("    kill register %s", value);
-            int regNum = asRegister(value).number;
-            assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof LIRInstruction && curInstruction != null;
-
-            if (end || curOutRegisterState[regNum] != curInstruction) {
-                curOutRegisterState[regNum] = null;
-            }
-
-        } else {
-            throw Util.shouldNotReachHere();
-        }
-        return value;
-    }
-
-    private CiValue killLocation(CiValue value) {
-        assert trace("    kill location %s", value);
-        assert isAllocatableRegister(asLocation(value).location);
-
-        int regNum = asRegister(asLocation(value).location).number;
-        if (curOutRegisterState[regNum] == value) {
-            curOutRegisterState[regNum] = null;
-        }
-        return null;
-    }
-
-    private CiValue block(CiValue value) {
-        if (isAllocatableRegister(value)) {
-            assert trace("    block %s", value);
-            int regNum = asRegister(value).number;
-            assert curInstruction != null;
-            assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof LIRInstruction;
-            curOutRegisterState[regNum] = curInstruction;
-        }
-        return value;
-    }
-
-    private CiValue load(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Input || mode == OperandMode.Alive;
-        if (flags.contains(OperandFlag.Stack)) {
-            return useSlot(value);
-        }
-        if (isVariable(value)) {
-            assert trace("    load %s", value);
-            Location regLoc = curRegisterLocations.get(asVariable(value));
-            if (regLoc != null) {
-                // This variable has already been processed before.
-                assert trace("      found location %s", regLoc);
-            } else {
-                regLoc = allocateRegister(asVariable(value), curInRegisterState, mode == OperandMode.Alive ? curOutRegisterState : null, mode, flags);
-                Location stackLoc = curStackLocations.get(asVariable(value));
-                assert stackLoc != null;
-                moveResolver.add(stackLoc, regLoc);
-            }
-            return regLoc;
-        } else {
-            assert !isAllocatableRegister(value) || curInRegisterState[asRegister(value).number] instanceof LIRInstruction;
-            return value;
-        }
-    }
-
-    private CiValue spill(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Temp || mode == OperandMode.Output;
-        if (flags.contains(OperandFlag.Stack)) {
-            return defSlot(value);
-        }
-        if (isVariable(value)) {
-            assert trace("    spill %s", value);
-            assert curStackLocations.get(asVariable(value)) == null;
-            Location regLoc = allocateRegister(asVariable(value), null, curOutRegisterState, mode, flags);
-            if (mode == OperandMode.Output) {
-                Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind));
-                curStackLocations.put(stackLoc);
-                moveResolver.add(regLoc, stackLoc);
-            }
-            return regLoc;
-        } else {
-            assert !isAllocatableRegister(value) || curOutRegisterState[asRegister(value).number] == curInstruction && curInstruction != null;
-            return value;
-        }
-    }
-
-    private CiValue useSlot(CiValue value) {
-        if (isVariable(value)) {
-            assert trace("    useSlot %s", value);
-            Location stackLoc = curStackLocations.get(asVariable(value));
-            assert stackLoc != null;
-            assert trace("      slot %s", stackLoc);
-            return stackLoc;
-        } else {
-            return value;
-        }
-    }
-
-    private CiValue defSlot(CiValue value) {
-        if (isVariable(value)) {
-            assert trace("    assignSlot %s", value);
-            Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind));
-            assert curStackLocations.get(asVariable(value)) == null;
-            curStackLocations.put(stackLoc);
-            assert trace("      slot %s", stackLoc);
-            return stackLoc;
-        } else {
-            return value;
-        }
-    }
-
-    private Location allocateRegister(final Variable variable, final Object[] inRegisterState, final Object[] outRegisterState, OperandMode mode, EnumSet<OperandFlag> flags) {
-        if (flags.contains(OperandFlag.RegisterHint)) {
-            CiValue result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() {
-                @Override
-                public CiValue doValue(CiValue registerHint) {
-                    assert trace("      registerHint %s", registerHint);
-                    CiRegister hint = null;
-                    if (isRegister(registerHint)) {
-                        hint = asRegister(registerHint);
-                    } else if (isLocation(registerHint) && isRegister(asLocation(registerHint).location)) {
-                        hint = asRegister(asLocation(registerHint).location);
-                    }
-                    if (hint != null && hint.isSet(variable.flag) && isFree(hint, inRegisterState, outRegisterState)) {
-                        return selectRegister(hint, variable, inRegisterState, outRegisterState);
-                    }
-                    return null;
-                }
-            });
-
-            if (result != null) {
-                return asLocation(result);
-            }
-        }
-
-        EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters();
-        CiRegister[] availableRegs = categorizedRegs.get(variable.flag);
-
-        for (CiRegister reg : availableRegs) {
-            if (isFree(reg, inRegisterState, outRegisterState)) {
-                return selectRegister(reg, variable, inRegisterState, outRegisterState);
-            }
-
-        }
-        throw new CiBailout("No register found");
-    }
-
-    private static boolean isFree(CiRegister reg, Object[] inRegisterState, Object[] outRegisterState) {
-        return (inRegisterState == null || inRegisterState[reg.number] == null) && (outRegisterState == null || outRegisterState[reg.number] == null);
-    }
-
-    private Location selectRegister(CiRegister reg, Variable variable, Object[] inRegisterState, Object[] outRegisterState) {
-        Location loc = new Location(variable, reg.asValue(variable.kind));
-        if (inRegisterState != null) {
-            inRegisterState[reg.number] = loc;
-        }
-        if (outRegisterState != null) {
-            outRegisterState[reg.number] = loc;
-        }
-        assert curRegisterLocations.get(variable) == null;
-        curRegisterLocations.put(loc);
-        assert trace("      selected register %s", loc);
-        return loc;
-    }
-
-    private boolean checkInputState(final Block block) {
-        final BitSet liveState = new BitSet();
-        curStackLocations.forEachLocation(new ValueProcedure() {
-            @Override
-            public CiValue doValue(CiValue value) {
-                liveState.set(asLocation(value).variable.index);
-
-                for (Block pred : block.getPredecessors()) {
-                    LocationMap predState = locationsFor(pred);
-                    if (predState != null) {
-                        assert predState.get(asLocation(value).variable) == value;
-                    } else {
-                        assert block.isLoopHeader();
-                    }
-                }
-                return value;
-            }
-        });
-        assert liveState.equals(curLiveIn);
-        return true;
-    }
-
-    private boolean checkNoCallerSavedRegister() {
-        for (CiRegister reg : frameMap.registerConfig.getCallerSaveRegisters()) {
-            assert curOutRegisterState[reg.number] == null || curOutRegisterState[reg.number] == curInstruction : "caller saved register in use accross call site";
-        }
-        return true;
-    }
-
-    private static boolean checkEmpty(Object[] array) {
-        for (Object o : array) {
-            assert o == null;
-        }
-        return true;
-    }
-
-
-    private boolean traceState() {
-        if (GraalOptions.TraceRegisterAllocation) {
-            TTY.print("  curVariableLocations: ");
-            curStackLocations.forEachLocation(new ValueProcedure() {
-                @Override
-                public CiValue doValue(CiValue value) {
-                    TTY.print("%s ", value);
-                    return value;
-                }
-            });
-            TTY.println();
-        }
-        return true;
-    }
-
-    private static boolean trace(String format, Object...args) {
-        if (GraalOptions.TraceRegisterAllocation) {
-            TTY.println(format, args);
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,293 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.alloc.util;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.alloc.simple.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
-
-public final class IntervalPrinter {
-
-    @SuppressWarnings("unused")
-    public static void printBeforeAllocation(String label, LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow) {
-        // TODO(tw): Fix printing.
-//        if (context.isObserved()) {
-//            IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, null);
-//            context.observable.fireCompilationEvent(label, lir, printer.execute());
-//        }
-    }
-
-    @SuppressWarnings("unused")
-    public static void printAfterAllocation(String label, LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow, LocationMap[] blockEndLocations) {
-        // TODO(tw): Fix printing.
-//        if (context.isObserved()) {
-//            IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, blockEndLocations);
-//            context.observable.fireCompilationEvent(label, lir, printer.execute());
-//        }
-    }
-
-
-    public static class Range {
-        public final int from;
-        public final int to;
-
-        public Range(int from, int to) {
-            this.from = from;
-            this.to = to;
-        }
-    }
-
-    public static class UsePosition {
-        public final int pos;
-        public final String kind;
-
-        public UsePosition(int pos, String kind) {
-            this.pos = pos;
-            this.kind = kind;
-        }
-    }
-
-    public static class Interval {
-        public final String name;
-        public final String description;
-        public final String variable;
-        public final String type;
-        public final List<Range> ranges;
-        public final List<UsePosition> uses;
-
-        protected final int orderNum;
-        protected int lastTo;
-
-        public Interval(int orderNum, String name, String description, String variable, String type) {
-            this.orderNum = orderNum;
-            this.name = name;
-            this.description = description;
-            this.variable = variable;
-            this.type = type;
-            this.ranges = new ArrayList<>();
-            this.uses = new ArrayList<>();
-        }
-    }
-
-
-    private final LIR lir;
-    private final RiRegisterConfig registerConfig;
-    private final DataFlowAnalysis dataFlow;
-    private final LocationMap[] blockEndLocations;
-    private final Variable[] variables;
-    private final Map<String, Interval> intervals;
-
-    private IntervalPrinter(LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow, LocationMap[] blockEndLocations) {
-        this.lir = lir;
-        this.registerConfig = registerConfig;
-        this.dataFlow = dataFlow;
-        this.blockEndLocations = blockEndLocations;
-        this.variables = new Variable[lir.numVariables()];
-        this.intervals = new HashMap<>();
-    }
-
-    private boolean isAllocatableRegister(CiValue value) {
-        return isRegister(value) && registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
-    }
-
-    private int curOpId;
-    private String curUseKind;
-
-    public Interval[] execute() {
-        ValueProcedure varProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return var(value); } };
-
-        for (Block block : lir.linearScanOrder()) {
-            if (block.phis != null) {
-                block.phis.forEachOutput(varProc);
-            }
-            for (LIRInstruction op : block.lir) {
-                op.forEachOutput(varProc);
-            }
-        }
-
-        PhiValueProcedure useProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
-        ValueProcedure    defProc = new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, flags); } };
-
-        intervals.put("call", new Interval(-2, "call", "", "call", "hasCall"));
-        intervals.put("st", new Interval(-1, "st", "", "st", "hasState"));
-
-        for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) {
-            Block block = lir.linearScanOrder().get(i);
-
-            curOpId = block.getLastLirInstructionId() + 2;
-            for (Block sux : block.getSuccessors()) {
-                BitSet suxIn = dataFlow.liveIn(sux);
-                for (int idx = suxIn.nextSetBit(0); idx >= 0; idx = suxIn.nextSetBit(idx + 1)) {
-                    if (blockEndLocations != null) {
-                        out(blockEndLocations[block.getId()].get(variables[idx]));
-                    } else {
-                        out(variables[idx]);
-                    }
-                }
-            }
-
-            curOpId = block.getLastLirInstructionId() + 1;
-            for (Block sux : block.getSuccessors()) {
-                if (sux.phis != null) {
-                    sux.phis.forEachInput(block, useProc);
-                }
-            }
-
-            for (int j = block.lir.size() - 1; j >= 0; j--) {
-                LIRInstruction op = block.lir.get(j);
-                if (op.id() >= 0) {
-                    curOpId = op.id();
-                } else {
-                    curOpId = (curOpId - 1) | 1;
-                }
-
-                op.forEachOutput(defProc);
-                op.forEachTemp(defProc);
-                op.forEachInput(useProc);
-                op.forEachAlive(useProc);
-                curUseKind = "L";
-                op.forEachState(useProc);
-                curUseKind = null;
-
-                if (op.hasCall()) {
-                    intervals.get("call").ranges.add(new Range(curOpId, curOpId + 1));
-                }
-                if (op.info != null) {
-                    intervals.get("st").ranges.add(new Range(curOpId, curOpId + 1));
-                }
-            }
-
-            if (block.phis != null) {
-                curOpId = block.getFirstLirInstructionId() + 1;
-                block.phis.forEachOutput(defProc);
-            }
-
-            for (Interval interval : intervals.values()) {
-                if (interval.lastTo != 0) {
-                    interval.ranges.add(new Range(block.getFirstLirInstructionId(), interval.lastTo));
-                    interval.lastTo = 0;
-                }
-            }
-        }
-
-        Interval[] intervalsArray = intervals.values().toArray(new Interval[0]);
-        Arrays.sort(intervalsArray, new Comparator<Interval>() {
-            @Override
-            public int compare(Interval o1, Interval o2) {
-                return o1.orderNum - o2.orderNum;
-            }
-        });
-        return intervalsArray;
-    }
-
-    public CiValue var(CiValue value) {
-        if (isLocation(value)) {
-            variables[asLocation(value).variable.index] = asLocation(value).variable;
-        } else if (isVariable(value)) {
-            variables[asVariable(value).index] = asVariable(value);
-        }
-        return value;
-    }
-
-    private Interval findInterval(CiValue value) {
-        Interval interval;
-        if (isLocation(value)) {
-            Interval parent = findInterval(asLocation(value).variable);
-            String name = "v" + asLocation(value).variable.index + ":" + asLocation(value).location;
-            String description = isStackSlot(asLocation(value).location) ? "stack" : "";
-            interval = new Interval(asLocation(value).variable.index * 2 + 1001, name, description, parent.name, value.kind.javaName);
-
-        } else if (isVariable(value)) {
-            interval = new Interval(asVariable(value).index * 2 + 1000, value.toString(), "", value.toString(), value.kind.javaName);
-
-        } else if (isAllocatableRegister(value)) {
-            interval = new Interval(asRegister(value).number, asRegister(value).toString(), "", asRegister(value).toString(), "fixed");
-
-        } else {
-            return null;
-        }
-
-        Interval existing = intervals.get(interval.name);
-        if (existing != null) {
-            return existing;
-        }
-        intervals.put(interval.name, interval);
-        return interval;
-    }
-
-    private String useKind(EnumSet<OperandFlag> flags) {
-        if (curUseKind != null) {
-            return curUseKind;
-        } else if (flags.contains(OperandFlag.Stack)) {
-            return "S";
-        } else {
-            return "M";
-        }
-    }
-
-    private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        Interval interval = findInterval(value);
-        if (interval != null) {
-            if (interval.uses.size() == 0 || interval.uses.get(interval.uses.size() - 1).pos != curOpId) {
-                interval.uses.add(new UsePosition(curOpId, useKind(flags)));
-            }
-            if (interval.lastTo == 0) {
-                interval.lastTo = curOpId + (mode == OperandMode.Alive ? 1 : 0);
-            }
-        }
-        return value;
-    }
-
-    private CiValue def(CiValue value, EnumSet<OperandFlag> flags) {
-        Interval interval = findInterval(value);
-        if (interval != null) {
-            interval.uses.add(new UsePosition(curOpId, useKind(flags)));
-            if (interval.lastTo == 0) {
-                interval.ranges.add(new Range(curOpId, curOpId + 1));
-            } else {
-                interval.ranges.add(new Range(curOpId, interval.lastTo));
-            }
-            interval.lastTo = 0;
-        }
-        return value;
-    }
-
-    private CiValue out(CiValue value) {
-        Interval interval = findInterval(value);
-        if (interval != null) {
-            interval.lastTo = curOpId;
-        }
-        return value;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/Location.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.alloc.util;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.lir.*;
-
-public class Location extends CiValue {
-    private static final long serialVersionUID = -1786677729152726126L;
-
-    public final Variable variable;
-    public final CiValue location;
-
-    public Location(Variable variable, CiValue location) {
-        super(variable.kind);
-        this.variable = variable;
-        this.location = location;
-
-        assert variable.kind == location.kind;
-    }
-
-    @Override
-    public String toString() {
-        return variable + "[" + location + "]";
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LocationMap.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.alloc.util;
-
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-
-public class LocationMap {
-    private final Location[] locations;
-
-    public LocationMap(int numVariables) {
-        locations = new Location[numVariables];
-    }
-
-    public LocationMap(LocationMap template) {
-        locations = Arrays.copyOf(template.locations, template.locations.length);
-    }
-
-    public Location get(Variable variable) {
-        assert locations[variable.index] == null || locations[variable.index].variable == variable;
-        return locations[variable.index];
-    }
-
-    public void put(Location location) {
-        locations[location.variable.index] = location;
-    }
-
-    public void clear(Variable variable) {
-        locations[variable.index] = null;
-    }
-
-    public void forEachLocation(ValueProcedure proc) {
-        for (int i = 0; i < locations.length; i++) {
-            if (locations[i] != null) {
-                CiValue newValue = proc.doValue(locations[i], null, null);
-                assert newValue == null || asLocation(newValue).variable == locations[i].variable;
-                locations[i] = (Location) newValue;
-            }
-        }
-    }
-
-    public boolean checkEmpty() {
-        for (int i = 0; i < locations.length; i++) {
-            assert locations[i] == null;
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,347 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.alloc.util;
-
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.alloc.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.util.*;
-
-public abstract class MoveResolver {
-    private final LIR lir;
-    private final FrameMap frameMap;
-    private final int[] registersBlocked;
-    private final Map<CiValue, Integer> valuesBlocked;
-    private final List<CiValue> mappingFrom;
-    private final List<Location> mappingTo;
-    private final LIRInsertionBuffer insertionBuffer;
-    private int insertPos;
-
-    public MoveResolver(LIR lir, FrameMap frameMap) {
-        this.lir = lir;
-        this.frameMap = frameMap;
-
-        registersBlocked = new int[frameMap.target.arch.registers.length];
-        valuesBlocked = new HashMap<>();
-
-        mappingFrom = new ArrayList<>();
-        mappingTo = new ArrayList<>();
-        insertionBuffer = new LIRInsertionBuffer();
-        insertPos = -1;
-
-        assert checkEmpty();
-    }
-
-    public void init(List<LIRInstruction> newInsertList, int newInsertPos) {
-        assert checkEmpty();
-
-        if (insertionBuffer.lirList() != newInsertList) {
-            // Block changed, so append insertionBuffer because it is bound to a specific block
-            finish();
-            insertionBuffer.init(newInsertList);
-        }
-        insertPos = newInsertPos;
-
-        assert checkValid();
-    }
-
-    public void add(CiValue from, Location to) {
-        assert checkValid();
-        assert isLocation(from) || isConstant(from);
-        assert from != to;
-
-        assert trace("mr    add mapping from %s to %s", from, to);
-        mappingFrom.add(from);
-        mappingTo.add(to);
-
-        assert checkValid();
-    }
-
-    public void resolve() {
-        assert checkValid();
-
-        if (mappingFrom.size() == 1) {
-            // If there is only one mapping, it is trivial that this mapping is safe to resolve.
-            assert trace("mr    resolve  mappings: %d", mappingFrom.size());
-            insertMove(mappingFrom.get(0), mappingTo.get(0));
-            mappingFrom.remove(0);
-            mappingTo.remove(0);
-        } else if (mappingFrom.size() > 1) {
-            assert trace("mr    resolve  mappings: %d", mappingFrom.size());
-            doResolve();
-        }
-        insertPos = -1;
-
-        assert checkEmpty();
-    }
-
-    public void finish() {
-        assert checkEmpty();
-
-        if (insertionBuffer.initialized()) {
-            insertionBuffer.finish();
-        }
-
-        assert !insertionBuffer.initialized() : "must be uninitialized now";
-        assert checkEmpty();
-    }
-
-
-    private void doResolve() {
-        // Block all registers and stack slots that are used as inputs of a move.
-        // When a register is blocked, no move to this register is emitted.
-        // This is necessary for detecting cycles in moves.
-        for (CiValue from : mappingFrom) {
-            block(from);
-        }
-
-        while (mappingFrom.size() > 0) {
-            boolean processed = false;
-            for (int i = mappingFrom.size() - 1; i >= 0; i--) {
-                CiValue from = mappingFrom.get(i);
-                Location to = mappingTo.get(i);
-
-                if (safeToProcessMove(from, to)) {
-                    insertMove(from, to);
-                    unblock(from);
-                    mappingFrom.remove(i);
-                    mappingTo.remove(i);
-                    processed = true;
-                }
-            }
-
-            if (!processed) {
-                // No move could be processed because there is a cycle in the move list
-                // (e.g., r1 -> r2, r2 -> r1), so one location must be spilled.
-                spill();
-            }
-        }
-    }
-
-    private void spill() {
-        Location spillCandidate = null;
-        int exchangeCandidate = -1;
-        int exchangeOther = -1;
-
-        for (int i = mappingFrom.size() - 1; i >= 0; i--) {
-            CiValue from = mappingFrom.get(i);
-            Location to = mappingTo.get(i);
-            assert !safeToProcessMove(from, to) : "would not be in this code otherwise";
-
-            if (isConstant(from)) {
-                continue;
-            }
-            CiValue fromLoc = asLocation(from).location;
-
-            // Check if we can insert an exchange to save us from spilling.
-            if (isRegister(fromLoc) && isRegister(to) && asRegister(fromLoc) != asRegister(to) && blockedCount(to) == 1) {
-                for (int j = mappingFrom.size() - 1; j >= 0; j--) {
-                    CiValue possibleOther = mappingFrom.get(j);
-                    if (isLocation(possibleOther)) {
-                        if (asLocation(possibleOther).location == to.location) {
-                            assert exchangeCandidate == -1 : "must not find twice because of blocked check above";
-                            exchangeCandidate = i;
-                            exchangeOther = j;
-                        } else if (i != j && asLocation(possibleOther).location == fromLoc) {
-                            // From is read multiple times, so exchange would be too complicated.
-                            exchangeCandidate = -1;
-                            break;
-                        }
-                    }
-                }
-            }
-
-            if (exchangeCandidate != -1) {
-                // Already found a result, no need to search further
-                break;
-            }
-            if (spillCandidate == null || isStackSlot(spillCandidate.location)) {
-                // this interval cannot be processed now because target is not free
-                spillCandidate = asLocation(from);
-            }
-        }
-
-        if (exchangeCandidate != -1) {
-            Location from = asLocation(mappingFrom.get(exchangeCandidate));
-            Location to = mappingTo.get(exchangeCandidate);
-            Location other = asLocation(mappingFrom.get(exchangeOther));
-
-            Location newOther = new Location(other.variable, from.variable);
-            mappingFrom.set(exchangeOther, newOther);
-
-            insertExchange(newOther, to);
-            unblock(to);
-            mappingFrom.remove(exchangeCandidate);
-            mappingTo.remove(exchangeCandidate);
-
-        } else {
-            assert spillCandidate != null : "no location for spilling found";
-
-            Location spillLocation = new Location(spillCandidate.variable, frameMap.allocateSpillSlot(spillCandidate.kind));
-            insertMove(spillCandidate, spillLocation);
-
-            for (int i = mappingFrom.size() - 1; i >= 0; i--) {
-                if (mappingFrom.get(i) == spillCandidate) {
-                    mappingFrom.set(i, spillLocation);
-                    unblock(spillCandidate);
-                    block(spillLocation);
-                }
-            }
-            assert blockedCount(spillCandidate) == 0 : "register must be unblocked after spilling";
-        }
-    }
-
-    private void block(CiValue value) {
-        if (isLocation(value)) {
-            CiValue location = asLocation(value).location;
-            if (isRegister(location)) {
-                registersBlocked[asRegister(location).number]++;
-            } else {
-                Integer count = valuesBlocked.get(location);
-                valuesBlocked.put(location, count == null ? 1 : count + 1);
-            }
-        }
-    }
-
-    private void unblock(CiValue value) {
-        if (isLocation(value)) {
-            assert blockedCount(asLocation(value)) > 0;
-            CiValue location = asLocation(value).location;
-            if (isRegister(location)) {
-                registersBlocked[asRegister(location).number]--;
-            } else {
-                Integer count = valuesBlocked.remove(location);
-                if (count > 1) {
-                    valuesBlocked.put(location, count - 1);
-                }
-            }
-        }
-    }
-
-    private int blockedCount(Location value) {
-        CiValue location = asLocation(value).location;
-        if (isRegister(location)) {
-            return registersBlocked[asRegister(location).number];
-        } else {
-            Integer count = valuesBlocked.get(location);
-            return count == null ? 0 : count;
-        }
-    }
-
-    private boolean safeToProcessMove(CiValue from, Location to) {
-        int count = blockedCount(to);
-        return count == 0 || (count == 1 && isLocation(from) && asLocation(from).location == to.location);
-    }
-
-    private void insertExchange(Location from, Location to) {
-        assert trace("mr      XCHG %s, %s", from, to);
-        // TODO create XCHG instruction and use it here
-        insertionBuffer.append(insertPos, null);
-        throw Util.unimplemented();
-    }
-
-    private void insertMove(CiValue src, Location dst) {
-        if (isStackSlot(dst.location) && isLocation(src) && isStackSlot(asLocation(src).location)) {
-            // Move between two stack slots. We need a temporary registers. If the allocator can give
-            // us a free register, we need two moves: src->scratch, scratch->dst
-            // If the allocator cannot give us a free register (it returns a Location in this case),
-            // we need to spill the scratch register first, so we need four moves in total.
-
-            CiValue scratch = scratchRegister(dst.variable);
-
-            Location scratchSaved = null;
-            CiValue scratchRegister = scratch;
-            if (isLocation(scratch)) {
-                scratchSaved = new Location(asLocation(scratch).variable, frameMap.allocateSpillSlot(scratch.kind));
-                insertMove(scratch, scratchSaved);
-                scratchRegister = asLocation(scratch).location;
-            }
-            assert isRegister(scratchRegister);
-
-            Location scratchLocation = new Location(dst.variable, scratchRegister);
-            insertMove(src, scratchLocation);
-            insertMove(scratchLocation, dst);
-
-            if (scratchSaved != null) {
-                insertMove(scratchSaved, asLocation(scratch));
-            }
-
-        } else {
-            assert trace("mr      MOV %s -> %s", src, dst);
-            insertionBuffer.append(insertPos, lir.spillMoveFactory.createMove(dst,  src));
-        }
-    }
-
-    /**
-     * Provides a register that can be used by the move resolver. If the returned value is a
-     * {@link CiRegisterValue}, the register can be overwritten without precautions. If the
-     * returned value is a {@link Location}, it needs to be spilled and rescued itself.
-     */
-    protected abstract CiValue scratchRegister(Variable spilled);
-
-    private boolean checkEmpty() {
-        assert insertPos == -1;
-        assert mappingFrom.size() == 0 && mappingTo.size() == 0;
-        for (int registerBlocked : registersBlocked) {
-            assert registerBlocked == 0;
-        }
-        assert valuesBlocked.size() == 0;
-        return true;
-    }
-
-    private boolean checkValid() {
-        assert insertPos != -1;
-        for (int registerBlocked : registersBlocked) {
-            assert registerBlocked == 0;
-        }
-        assert mappingFrom.size() == mappingTo.size();
-        assert insertionBuffer.initialized() && insertPos != -1;
-
-        for (int i = 0; i < mappingTo.size(); i++) {
-            CiValue from = mappingFrom.get(i);
-            Location to = mappingTo.get(i);
-
-            assert from.kind.stackKind() == to.kind;
-
-            for (int j = i + 1; j < mappingTo.size(); j++) {
-                Location otherTo = mappingTo.get(j);
-                assert to != otherTo && to.variable != otherTo.variable && to.location != otherTo.location : "Cannot write to same location twice";
-            }
-        }
-        return true;
-    }
-
-
-    private static boolean trace(String format, Object...args) {
-        if (GraalOptions.TraceRegisterAllocation) {
-            TTY.println(format, args);
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,260 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.alloc.util;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.*;
-import com.oracle.max.graal.compiler.util.*;
-
-public final class RegisterVerifier {
-    private final FrameMap frameMap;
-
-    /**
-     * All blocks that must be processed.
-     */
-    private final List<Block> workList;
-
-    /**
-     * Saved information of previous check.
-     * <br>
-     * State mapping: mapping from registers and stack slots ({@link CiRegister} and {@link Integer} stack slot offsets) to the
-     * value that is currently contained in there ({@link Location} for operands that were variables; {@link CiRegisterValue} or
-     * {@link CiStackSlot} for operands that used fixed registers or stack slots).
-     */
-    private final Map<Object, CiValue>[] blockStates;
-
-    private void addToWorkList(Block block) {
-        if (!workList.contains(block)) {
-            workList.add(block);
-        }
-    }
-
-    private Map<Object, CiValue> stateFor(Block block) {
-        return blockStates[block.getId()];
-    }
-
-    private void setStateFor(Block block, Map<Object, CiValue> savedState) {
-        blockStates[block.getId()] = savedState;
-    }
-
-    private static Map<Object, CiValue> copy(Map<Object, CiValue> inputState) {
-        return new HashMap<>(inputState);
-    }
-
-    public static boolean verify(LIR lir, FrameMap frameMap) {
-        RegisterVerifier verifier = new RegisterVerifier(lir, frameMap);
-        verifier.verify(lir.cfg.getStartBlock());
-        return true;
-    }
-
-    @SuppressWarnings("unchecked")
-    private RegisterVerifier(LIR lir, FrameMap frameMap) {
-        this.frameMap = frameMap;
-        this.workList = new LinkedList<>();
-        this.blockStates = new Map[lir.linearScanOrder().size()];
-    }
-
-    private Map<Object, CiValue> curInputState;
-
-    private void verify(Block startBlock) {
-        ValueProcedure useProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, flags); } };
-        ValueProcedure tempProc =   new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return temp(value); } };
-        ValueProcedure outputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return output(value); } };
-
-        curInputState = new HashMap<>();
-        setStateFor(startBlock, curInputState);
-        addToWorkList(startBlock);
-
-        assert trace("==== start verify register allocation ====");
-        do {
-            Block block = workList.remove(0);
-            assert block.phis == null : "phi functions must have been resolved with moves";
-
-            // Must copy state because it is modified.
-            curInputState = copy(stateFor(block));
-            assert trace("start block %s %s", block, block.getLoop());
-            assert traceState();
-
-            for (LIRInstruction op : block.lir) {
-                assert trace("  op %d %s", op.id(), op);
-
-                op.forEachInput(useProc);
-                if (op.hasCall()) {
-                    invalidateRegisters();
-                }
-                op.forEachAlive(useProc);
-                op.forEachState(useProc);
-                op.forEachTemp(tempProc);
-                op.forEachOutput(outputProc);
-            }
-
-            for (Block succ : block.getSuccessors()) {
-                processSuccessor(succ);
-            }
-
-            assert trace("end block %s", block);
-        } while (!workList.isEmpty());
-        assert trace("==== end verify register allocation ====");
-    }
-
-    private void processSuccessor(Block succ) {
-        Map<Object, CiValue> savedState = stateFor(succ);
-        if (savedState == null) {
-            // Block was not processed before, so set initial inputState.
-            assert trace("  successor %s: initial visit", succ);
-            setStateFor(succ, copy(curInputState));
-            addToWorkList(succ);
-
-        } else {
-            // This block was already processed before.
-            // Check if new inputState is consistent with savedState.
-            assert trace("  successor %s: state present", succ);
-            Iterator<Map.Entry<Object, CiValue>> iter = savedState.entrySet().iterator();
-            while (iter.hasNext()) {
-                Map.Entry<Object, CiValue> entry = iter.next();
-                CiValue savedValue = entry.getValue();
-                CiValue inputValue = curInputState.get(entry.getKey());
-
-                if (savedValue != inputValue) {
-                    // Current inputState and previous savedState assume a different value in this register.
-                    // Assume that this register is invalid and remove it from the saved state.
-                    assert trace("    invalididating %s because it is inconsistent with %s", savedValue, inputValue);
-                    iter.remove();
-                    // Must re-visit this block.
-                    addToWorkList(succ);
-                }
-            }
-        }
-    }
-
-    private void invalidateRegisters() {
-        // Invalidate all caller save registers at calls.
-        Iterator<Object> iter = curInputState.keySet().iterator();
-        while (iter.hasNext()) {
-            Object value1 = iter.next();
-            if (value1 instanceof CiRegister && frameMap.registerConfig.getAttributesMap()[((CiRegister) value1).number].isCallerSave) {
-                assert trace("    remove caller save register %s", value1);
-                iter.remove();
-            }
-        }
-    }
-
-    /**
-     * Gets the mapping key for a value. The key should be as narrow as possible, e.g., it should not
-     * include the kind of the value because we do not want to distinguish between the same register with
-     * different kinds.
-     */
-    private Object key(CiValue value) {
-        if (isLocation(value)) {
-            return key(asLocation(value).location);
-        } else if (isRegister(value)) {
-            return asRegister(value);
-        } else if (isStackSlot(value)) {
-            return Integer.valueOf(frameMap.offsetForStackSlot(asStackSlot(value)));
-        } else {
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-    private boolean isIgnoredRegister(CiValue value) {
-        return isRegister(value) && !frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
-    }
-
-    private CiValue use(CiValue value, EnumSet<OperandFlag> flags) {
-        if (!isConstant(value) && value != CiValue.IllegalValue && !isIgnoredRegister(value)) {
-            CiValue actual = curInputState.get(key(value));
-            if (actual == null && flags.contains(OperandFlag.Uninitialized)) {
-                // OK, since uninitialized values are allowed explicitly.
-            } else if (value != actual) {
-                TTY.println("!! Error in register allocation: %s != %s for key %s", value, actual, key(value));
-                traceState();
-                throw Util.shouldNotReachHere();
-            }
-        }
-        return value;
-    }
-
-    private CiValue temp(CiValue value) {
-        if (!isConstant(value) && value != CiValue.IllegalValue && !isIgnoredRegister(value)) {
-            assert trace("    temp %s -> remove key %s", value, key(value));
-            curInputState.remove(key(value));
-        }
-        return value;
-    }
-
-    private CiValue output(CiValue value) {
-        if (value != CiValue.IllegalValue && !isIgnoredRegister(value)) {
-            assert trace("    output %s -> set key %s", value, key(value));
-            curInputState.put(key(value), value);
-        }
-        return value;
-    }
-
-
-    private boolean traceState() {
-        if (GraalOptions.TraceRegisterAllocation) {
-            ArrayList<Object> keys = new ArrayList<>(curInputState.keySet());
-            Collections.sort(keys, new Comparator<Object>() {
-                @Override
-                public int compare(Object o1, Object o2) {
-                    if (o1 instanceof CiRegister) {
-                        if (o2 instanceof CiRegister) {
-                            return ((CiRegister) o1).number - ((CiRegister) o2).number;
-                        } else {
-                            return -1;
-                        }
-                    } else {
-                        if (o2 instanceof CiRegister) {
-                            return 1;
-                        } else {
-                            return ((Integer) o1).intValue() - ((Integer) o2).intValue();
-                        }
-                    }
-                }
-            });
-
-            TTY.print("    state: ");
-            for (Object key : keys) {
-                TTY.print("%s=%s  ", key, curInputState.get(key));
-            }
-            TTY.println();
-        }
-        return true;
-    }
-
-    private static boolean trace(String format, Object...args) {
-        if (GraalOptions.TraceRegisterAllocation) {
-            TTY.println(format, args);
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/ValueUtil.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.alloc.util;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.lir.*;
-
-public class ValueUtil extends CiValueUtil {
-
-    public static boolean isVariable(CiValue value) {
-        assert value != null;
-        return value instanceof Variable;
-    }
-
-    public static Variable asVariable(CiValue value) {
-        assert value != null;
-        return (Variable) value;
-    }
-
-
-    public static boolean isLocation(CiValue value) {
-        assert value != null;
-        return value instanceof Location;
-    }
-
-    public static Location asLocation(CiValue value) {
-        assert value != null;
-        return (Location) value;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Wed Feb 08 21:15:00 2012 -0800
@@ -29,19 +29,18 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.cri.xir.*;
-import com.oracle.max.criutils.*;
 import com.oracle.max.graal.alloc.simple.*;
 import com.oracle.max.graal.compiler.alloc.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.phases.*;
 import com.oracle.max.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.target.*;
 import com.oracle.max.graal.cri.*;
 import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.asm.*;
+import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 
 public class GraalCompiler {
@@ -81,7 +80,10 @@
         if (osrBCI != -1) {
             throw new CiBailout("No OSR supported");
         }
-        return Debug.scope(createScopeName(method), method, new Callable<CiTargetMethod>() {
+        Debug.dump(this, "compiler");
+        Debug.dump(method, "method");
+
+        return Debug.scope(createScopeName(method), new Callable<CiTargetMethod>() {
             public CiTargetMethod call() {
                 final CiAssumptions assumptions = GraalOptions.OptAssumptions ? new CiAssumptions() : null;
                 final LIR lir = Debug.scope("FrontEnd", graph, new Callable<LIR>() {
@@ -189,6 +191,7 @@
 
         final SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
+        Debug.dump(schedule, "final schedule");
 
         final Block[] blocks = schedule.getCFG().getBlocks();
         final Block startBlock = schedule.getCFG().getStartBlock();
@@ -219,6 +222,7 @@
     public FrameMap emitLIR(final LIR lir, StructuredGraph graph, final RiResolvedMethod method) {
         final FrameMap frameMap = backend.newFrameMap(runtime.getRegisterConfig(method));
         final LIRGenerator lirGenerator = backend.newLIRGenerator(graph, frameMap, method, lir, xir);
+        Debug.dump(lirGenerator, "LIRGenerator");
 
         Debug.scope("LIRGen", new Runnable() {
             public void run() {
@@ -226,16 +230,7 @@
                     lirGenerator.doBlock(b);
                 }
 
-                for (Block b : lir.linearScanOrder()) {
-                    if (b.phis != null) {
-                        b.phis.fillInputs(lirGenerator);
-                    }
-                }
-
-                Debug.dump(lirGenerator, "After LIR generation");
-                if (GraalOptions.PrintLIR && !TTY.isSuppressed()) {
-                    LIR.printLIR(lir.linearScanOrder());
-                }
+                Debug.dump(lir, "After LIR generation");
             }
         });
 
@@ -269,6 +264,7 @@
             targetMethod.setAssumptions(assumptions);
         }
 
+        Debug.dump(lir, "After code generation");
         Debug.dump(targetMethod, "After code generation");
         return targetMethod;
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ComputeLinearScanOrder.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ComputeLinearScanOrder.java	Wed Feb 08 21:15:00 2012 -0800
@@ -27,8 +27,8 @@
 
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.cfg.*;
 
 public final class ComputeLinearScanOrder {
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java	Wed Feb 08 21:15:00 2012 -0800
@@ -24,10 +24,10 @@
 
 import java.util.*;
 
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.cfg.*;
 
 /**
  * This class performs basic optimizations on the control flow graph after LIR generation.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java	Wed Feb 08 21:15:00 2012 -0800
@@ -24,9 +24,9 @@
 
 import java.util.*;
 
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.StandardOp.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.StandardOp.*;
+import com.oracle.max.graal.lir.cfg.*;
 
 /**
  * This class optimizes moves, particularly those that result from eliminating SSA form.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/Interval.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/Interval.java	Wed Feb 08 21:15:00 2012 -0800
@@ -22,15 +22,15 @@
  */
 package com.oracle.max.graal.compiler.alloc;
 
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
+import static com.oracle.max.graal.alloc.util.LocationUtil.*;
 
 import java.util.*;
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.lir.*;
 
 /**
  * Represents an interval in the {@linkplain LinearScan linear scan register allocator}.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LIRInsertionBuffer.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.alloc;
-
-import java.util.*;
-
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.util.*;
-
-/**
- * A buffer to enqueue updates to a list. This avoids frequent re-sizing of the list and copying of list elements
- * when insertions are done at multiple positions of the list. Additionally, it ensures that the list is not modified
- * while it is, e.g., iterated, and instead only modified once after the iteration is done.
- * <br>
- * The buffer uses internal data structures to store the enqueued updates. To avoid allocations, a buffer can be re-used.
- * Call the methods in the following order:
- * {@link #init()}, {@link #append()}, {@link #append()}, ..., {@link #finish()}, {@link #init()}, ...
- * <br>
- * Note: This class does not depend on LIRInstruction, so we could make it a generic utility class.
- */
-public final class LIRInsertionBuffer {
-
-    /**
-     * The lir list where ops of this buffer should be inserted later (null when uninitialized).
-     */
-    private List<LIRInstruction> lir;
-
-    /**
-     * List of insertion points. index and count are stored alternately:
-     * indexAndCount[i * 2]: the index into lir list where "count" ops should be inserted
-     * indexAndCount[i * 2 + 1]: the number of ops to be inserted at index
-     */
-    private final IntList indexAndCount;
-
-    /**
-     * The LIROps to be inserted.
-     */
-    private final List<LIRInstruction> ops;
-
-
-    public LIRInsertionBuffer() {
-        indexAndCount = new IntList(8);
-        ops = new ArrayList<>(8);
-    }
-
-    /**
-     * Initialize this buffer. This method must be called before using {@link #append()}.
-     */
-    public void init(List<LIRInstruction> newLir) {
-        assert !initialized() : "already initialized";
-        assert indexAndCount.size() == 0 && ops.size() == 0;
-        this.lir = newLir;
-    }
-
-    public boolean initialized() {
-        return lir != null;
-    }
-
-    public List<LIRInstruction> lirList() {
-        return lir;
-    }
-
-    /**
-     * Enqueue a new instruction that will be appended to the instruction list when {@link #finish()} is called.
-     * The new instruction is added <b>before</b> the existing instruction with the given index. This method can only be called
-     * with increasing values of index, e.g., once an instruction was appended with index 4, subsequent instructions can
-     * only be appended with index 4 or higher.
-     */
-    public void append(int index, LIRInstruction op) {
-        int i = numberOfInsertionPoints() - 1;
-        if (i < 0 || indexAt(i) < index) {
-            appendNew(index, 1);
-        } else {
-            assert indexAt(i) == index : "can append LIROps in ascending order only";
-            assert countAt(i) > 0 : "check";
-            setCountAt(i, countAt(i) + 1);
-        }
-        ops.add(op);
-
-        assert verify();
-    }
-
-    /**
-     * Append all enqueued instructions to the instruction list. After that, {@link init()} can be called again to re-use this buffer.
-     */
-    public void finish() {
-        if (ops.size() > 0) {
-            int n = lir.size();
-            // increase size of instructions list
-            for (int i = 0; i < ops.size(); i++) {
-                lir.add(null);
-            }
-            // insert ops from buffer into instructions list
-            int opIndex = ops.size() - 1;
-            int ipIndex = numberOfInsertionPoints() - 1;
-            int fromIndex = n - 1;
-            int toIndex = lir.size() - 1;
-            while (ipIndex >= 0) {
-                int index = indexAt(ipIndex);
-                // make room after insertion point
-                while (fromIndex >= index) {
-                    lir.set(toIndex--, lir.get(fromIndex--));
-                }
-                // insert ops from buffer
-                for (int i = countAt(ipIndex); i > 0; i--) {
-                    lir.set(toIndex--, ops.get(opIndex--));
-                }
-                ipIndex--;
-            }
-            indexAndCount.clear();
-            ops.clear();
-        }
-        lir = null;
-    }
-
-    private void appendNew(int index, int count) {
-        indexAndCount.add(index);
-        indexAndCount.add(count);
-    }
-
-    private void setCountAt(int i, int value) {
-        indexAndCount.set((i << 1) + 1, value);
-    }
-
-    private int numberOfInsertionPoints() {
-        assert indexAndCount.size() % 2 == 0 : "must have a count for each index";
-        return indexAndCount.size() >> 1;
-    }
-
-    private int indexAt(int i) {
-        return indexAndCount.get((i << 1));
-    }
-
-    private int countAt(int i) {
-        return indexAndCount.get((i << 1) + 1);
-    }
-
-    private boolean verify() {
-        int sum = 0;
-        int prevIdx = -1;
-
-        for (int i = 0; i < numberOfInsertionPoints(); i++) {
-            assert prevIdx < indexAt(i) : "index must be ordered ascending";
-            sum += countAt(i);
-        }
-        assert sum == ops.size() : "wrong total sum";
-        return true;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Wed Feb 08 21:15:00 2012 -0800
@@ -24,7 +24,7 @@
 
 import static com.oracle.max.cri.ci.CiUtil.*;
 import static com.oracle.max.cri.ci.CiValueUtil.*;
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
+import static com.oracle.max.graal.alloc.util.LocationUtil.*;
 
 import java.util.*;
 
@@ -35,16 +35,14 @@
 import com.oracle.max.graal.compiler.alloc.Interval.RegisterBinding;
 import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority;
 import com.oracle.max.graal.compiler.alloc.Interval.SpillState;
-import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.StandardOp.MoveOp;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.LIRInstruction.*;
+import com.oracle.max.graal.lir.StandardOp.*;
+import com.oracle.max.graal.lir.cfg.*;
 
 /**
  * An implementation of the linear scan register allocator algorithm described
@@ -1589,7 +1587,7 @@
                 }
 
                 default: {
-                    throw Util.shouldNotReachHere();
+                    throw GraalInternalError.shouldNotReachHere();
                 }
             }
         }
@@ -1902,14 +1900,6 @@
     }
 
     void printLir(String label, @SuppressWarnings("unused") boolean hirValid) {
-        // TODO(tw): Fix printing.
-        if (GraalOptions.TraceLinearScanLevel >= 1 && !TTY.isSuppressed()) {
-            TTY.println();
-            TTY.println(label);
-            LIR.printLIR(ir.linearScanOrder());
-            TTY.println();
-        }
-
         Debug.dump(ir, label);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java	Wed Feb 08 21:15:00 2012 -0800
@@ -23,7 +23,7 @@
 package com.oracle.max.graal.compiler.alloc;
 
 import static com.oracle.max.cri.ci.CiUtil.*;
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
+import static com.oracle.max.graal.alloc.util.LocationUtil.*;
 
 import java.util.*;
 
@@ -35,10 +35,10 @@
 import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority;
 import com.oracle.max.graal.compiler.alloc.Interval.SpillState;
 import com.oracle.max.graal.compiler.alloc.Interval.State;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.compiler.lir.StandardOp.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.StandardOp.*;
+import com.oracle.max.graal.lir.cfg.*;
 
 /**
  */
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java	Wed Feb 08 21:15:00 2012 -0800
@@ -29,7 +29,7 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.lir.*;
 
 /**
  */
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java	Wed Feb 08 21:15:00 2012 -0800
@@ -29,10 +29,10 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.*;
 import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.LIRInstruction.*;
+import com.oracle.max.graal.lir.cfg.*;
 
 /**
  */
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/ExceptionInfo.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.asm;
-
-import com.oracle.max.graal.compiler.lir.*;
-
-public class ExceptionInfo {
-
-    public final int codeOffset;
-    public final LabelRef exceptionEdge;
-    public final int bci;
-
-    public ExceptionInfo(int pcOffset, LabelRef exceptionEdge, int bci) {
-        this.codeOffset = pcOffset;
-        this.exceptionEdge = exceptionEdge;
-        this.bci = bci;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/TargetMethodAssembler.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,268 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.asm;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.asm.*;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIR.SlowPath;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.debug.*;
-
-public class TargetMethodAssembler {
-
-    public final AbstractAssembler asm;
-    public final CiTargetMethod targetMethod;
-    public final CiTarget target;
-    public final RiRuntime runtime;
-    public final FrameMap frameMap;
-    public final List<SlowPath> slowPaths;
-
-    private List<ExceptionInfo> exceptionInfoList;
-    private int lastSafepointPos;
-    public TargetMethodAssembler(CiTarget target, RiRuntime runtime, FrameMap frameMap, List<SlowPath> slowPaths, AbstractAssembler asm) {
-        this.target = target;
-        this.runtime = runtime;
-        this.frameMap = frameMap;
-        this.slowPaths = slowPaths;
-        this.asm = asm;
-        this.targetMethod = new CiTargetMethod();
-        // 0 is a valid pc for safepoints in template methods
-        this.lastSafepointPos = -1;
-    }
-
-    public void setFrameSize(int frameSize) {
-        targetMethod.setFrameSize(frameSize);
-    }
-
-    public CiTargetMethod.Mark recordMark(Object id, CiTargetMethod.Mark[] references) {
-        return targetMethod.recordMark(asm.codeBuffer.position(), id, references);
-    }
-
-    public void blockComment(String s) {
-        targetMethod.addAnnotation(new CiTargetMethod.CodeComment(asm.codeBuffer.position(), s));
-    }
-
-    public CiTargetMethod finishTargetMethod(Object name, boolean isStub) {
-        // Install code, data and frame size
-        targetMethod.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position());
-
-        // Record exception handlers if they exist
-        if (exceptionInfoList != null) {
-            for (ExceptionInfo ei : exceptionInfoList) {
-                int codeOffset = ei.codeOffset;
-                targetMethod.recordExceptionHandler(codeOffset, -1, 0, ei.exceptionEdge.label().position(), -1, null);
-            }
-        }
-
-        Debug.metric("TargetMethods").increment();
-        Debug.metric("CodeBytesEmitted").add(targetMethod.targetCodeSize());
-        Debug.metric("SafepointsEmitted").add(targetMethod.safepoints.size());
-        Debug.metric("DataPatches").add(targetMethod.dataReferences.size());
-        Debug.metric("ExceptionHandlersEmitted").add(targetMethod.exceptionHandlers.size());
-
-        if (GraalOptions.PrintAssembly && !TTY.isSuppressed() && !isStub) {
-            Util.printSection("Target Method", Util.SECTION_CHARACTER);
-            TTY.println("Name: " + name);
-            TTY.println("Frame size: " + targetMethod.frameSize());
-            TTY.println("Register size: " + asm.target.arch.registerReferenceMapBitCount);
-
-            if (GraalOptions.PrintCodeBytes) {
-                Util.printSection("Code", Util.SUB_SECTION_CHARACTER);
-                TTY.println("Code: %d bytes", targetMethod.targetCodeSize());
-                Util.printBytes(0L, targetMethod.targetCode(), 0, targetMethod.targetCodeSize(), GraalOptions.PrintAssemblyBytesPerLine);
-            }
-
-            Util.printSection("Disassembly", Util.SUB_SECTION_CHARACTER);
-            String disassembly = runtime.disassemble(targetMethod);
-            TTY.println(disassembly);
-            boolean noDis = disassembly == null || disassembly.length() == 0;
-
-            Util.printSection("Safepoints", Util.SUB_SECTION_CHARACTER);
-            for (CiTargetMethod.Safepoint x : targetMethod.safepoints) {
-                TTY.println(x.toString());
-                if (noDis && x.debugInfo != null) {
-                    TTY.println(CiUtil.indent(x.debugInfo.toString(), "  "));
-                }
-            }
-
-            Util.printSection("Data Patches", Util.SUB_SECTION_CHARACTER);
-            for (CiTargetMethod.DataPatch x : targetMethod.dataReferences) {
-                TTY.println(x.toString());
-            }
-
-            Util.printSection("Marks", Util.SUB_SECTION_CHARACTER);
-            for (CiTargetMethod.Mark x : targetMethod.marks) {
-                TTY.println(x.toString());
-            }
-
-            Util.printSection("Exception Handlers", Util.SUB_SECTION_CHARACTER);
-            for (CiTargetMethod.ExceptionHandler x : targetMethod.exceptionHandlers) {
-                TTY.println(x.toString());
-            }
-        }
-
-        return targetMethod;
-    }
-
-    public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) {
-        if (info != null) {
-            if (info.exceptionEdge != null) {
-                if (exceptionInfoList == null) {
-                    exceptionInfoList = new ArrayList<>(4);
-                }
-                exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionEdge, info.topFrame.bci));
-            }
-        }
-    }
-
-    public void recordImplicitException(int pcOffset, LIRDebugInfo info) {
-        // record an implicit exception point
-        if (info != null) {
-            assert lastSafepointPos < pcOffset : lastSafepointPos + "<" + pcOffset;
-            lastSafepointPos = pcOffset;
-            targetMethod.recordSafepoint(pcOffset, info.debugInfo());
-            assert info.exceptionEdge == null;
-        }
-    }
-
-    public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRDebugInfo info) {
-        CiDebugInfo debugInfo = info != null ? info.debugInfo() : null;
-        assert lastSafepointPos < posAfter;
-        lastSafepointPos = posAfter;
-        targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, true);
-    }
-
-    public void recordIndirectCall(int posBefore, int posAfter, Object callTarget, LIRDebugInfo info) {
-        CiDebugInfo debugInfo = info != null ? info.debugInfo() : null;
-        assert lastSafepointPos < posAfter;
-        lastSafepointPos = posAfter;
-        targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false);
-    }
-
-    public void recordSafepoint(int pos, LIRDebugInfo info) {
-        // safepoints always need debug info
-        CiDebugInfo debugInfo = info.debugInfo();
-        assert lastSafepointPos < pos;
-        lastSafepointPos = pos;
-        targetMethod.recordSafepoint(pos, debugInfo);
-    }
-
-    public CiAddress recordDataReferenceInCode(CiConstant data, int alignment) {
-        assert data != null;
-        int pos = asm.codeBuffer.position();
-        Debug.log("Data reference in code: pos = %d, data = %s", pos, data.toString());
-        targetMethod.recordDataReference(pos, data, alignment);
-        return CiAddress.Placeholder;
-    }
-
-    public int lastSafepointPos() {
-        return lastSafepointPos;
-    }
-
-
-    /**
-     * Returns the integer value of any constants that can be represented by a 32-bit integer value,
-     * including long constants that fit into the 32-bit range.
-     */
-    public int asIntConst(CiValue value) {
-        assert (value.kind.stackKind() == CiKind.Int || value.kind == CiKind.Jsr || value.kind == CiKind.Long) && isConstant(value);
-        long c = ((CiConstant) value).asLong();
-        if (!(NumUtil.isInt(c))) {
-            throw Util.shouldNotReachHere();
-        }
-        return (int) c;
-    }
-
-    /**
-     * Returns the address of a float constant that is embedded as a data references into the code.
-     */
-    public CiAddress asFloatConstRef(CiValue value) {
-        return asFloatConstRef(value, 4);
-    }
-
-    public CiAddress asFloatConstRef(CiValue value, int alignment) {
-        assert value.kind == CiKind.Float && isConstant(value);
-        return recordDataReferenceInCode((CiConstant) value, alignment);
-    }
-
-    /**
-     * Returns the address of a double constant that is embedded as a data references into the code.
-     */
-    public CiAddress asDoubleConstRef(CiValue value) {
-        return asDoubleConstRef(value, 8);
-    }
-
-    public CiAddress asDoubleConstRef(CiValue value, int alignment) {
-        assert value.kind == CiKind.Double && isConstant(value);
-        return recordDataReferenceInCode((CiConstant) value, alignment);
-    }
-
-    /**
-     * Returns the address of a long constant that is embedded as a data references into the code.
-     */
-    public CiAddress asLongConstRef(CiValue value) {
-        assert value.kind == CiKind.Long && isConstant(value);
-        return recordDataReferenceInCode((CiConstant) value, 8);
-    }
-
-    public CiAddress asIntAddr(CiValue value) {
-        assert value.kind == CiKind.Int;
-        return asAddress(value);
-    }
-
-    public CiAddress asLongAddr(CiValue value) {
-        assert value.kind == CiKind.Long;
-        return asAddress(value);
-    }
-
-    public CiAddress asObjectAddr(CiValue value) {
-        assert value.kind == CiKind.Object;
-        return asAddress(value);
-    }
-
-    public CiAddress asFloatAddr(CiValue value) {
-        assert value.kind == CiKind.Float;
-        return asAddress(value);
-    }
-
-    public CiAddress asDoubleAddr(CiValue value) {
-        assert value.kind == CiKind.Double;
-        return asAddress(value);
-    }
-
-    public CiAddress asAddress(CiValue value) {
-        if (isStackSlot(value)) {
-            CiStackSlot slot = (CiStackSlot) value;
-            return new CiAddress(slot.kind, frameMap.registerConfig.getFrameRegister().asValue(), frameMap.offsetForStackSlot(slot));
-        }
-        return (CiAddress) value;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Block.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.cfg;
-
-import java.util.*;
-
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.nodes.*;
-import com.oracle.max.graal.nodes.java.*;
-
-public class Block {
-    protected int id;
-
-    protected BeginNode beginNode;
-    protected Node endNode;
-    protected Loop loop;
-    protected double probability;
-
-    protected List<Block> predecessors;
-    protected List<Block> successors;
-
-    protected Block dominator;
-    protected List<Block> dominated;
-    protected Block postdominator;
-
-    // Fields that still need to be worked on, try to remove them later.
-    public FrameState lastState;
-    public List<LIRInstruction> lir;
-    public boolean align;
-    public int linearScanNumber;
-    public LIRPhiMapping phis;
-
-    public Block() {
-        id = -1;
-    }
-
-    public int getId() {
-        assert id >= 0;
-        return id;
-    }
-
-    public BeginNode getBeginNode() {
-        return beginNode;
-    }
-
-    public Node getEndNode() {
-        return endNode;
-    }
-
-    public Loop getLoop() {
-        return loop;
-    }
-
-    public int getLoopDepth() {
-        return loop == null ? 0 : loop.depth;
-    }
-
-    public boolean isLoopHeader() {
-        return getBeginNode() instanceof LoopBeginNode;
-    }
-
-    public boolean isLoopEnd() {
-        return getEndNode() instanceof LoopEndNode;
-    }
-
-    public boolean isExceptionEntry() {
-        return getBeginNode().next() instanceof ExceptionObjectNode;
-    }
-
-    public List<Block> getPredecessors() {
-        return predecessors;
-    }
-
-    public List<Block> getSuccessors() {
-        return successors;
-    }
-
-    public Block getDominator() {
-        return dominator;
-    }
-
-    public List<Block> getDominated() {
-        if (dominated == null) {
-            return Collections.emptyList();
-        }
-        return dominated;
-    }
-
-    public Block getPostdominator() {
-        return postdominator;
-    }
-
-    private class NodeIterator implements Iterator<Node> {
-        private Node cur;
-
-        public NodeIterator() {
-            cur = getBeginNode();
-        }
-
-        @Override
-        public boolean hasNext() {
-            return cur != null;
-        }
-
-        @Override
-        public Node next() {
-            Node result = cur;
-            if (cur == getEndNode()) {
-                cur = null;
-            } else {
-                cur = ((FixedWithNextNode) cur).next();
-            }
-            assert !(cur instanceof BeginNode);
-            return result;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    public Iterable<Node> getNodes() {
-        return new Iterable<Node>() {
-            @Override
-            public Iterator<Node> iterator() {
-                return new NodeIterator();
-            }
-        };
-    }
-
-    public int getFirstLirInstructionId() {
-        int result = lir.get(0).id();
-        assert result >= 0;
-        return result;
-    }
-
-    public int getLastLirInstructionId() {
-        int result = lir.get(lir.size() - 1).id();
-        assert result >= 0;
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "B" + id;
-    }
-
-
-// to be inlined later on
-    public int numberOfPreds() {
-        return getPredecessors().size();
-    }
-
-    public int numberOfSux() {
-        return getSuccessors().size();
-    }
-
-    public Block predAt(int i) {
-        return getPredecessors().get(i);
-    }
-
-    public Block suxAt(int i) {
-        return getSuccessors().get(i);
-    }
-// end to be inlined later on
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/BlockMap.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.cfg;
-
-public class BlockMap<T> {
-    private final T[] data;
-
-    @SuppressWarnings("unchecked")
-    public BlockMap(ControlFlowGraph cfg) {
-        data = (T[]) new Object[cfg.getBlocks().length];
-    }
-
-    public T get(Block block) {
-        return data[block.getId()];
-    }
-
-    public void put(Block block, T value) {
-        data[block.getId()] = value;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/CFGVerifier.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.cfg;
-
-public class CFGVerifier {
-    public static boolean verify(ControlFlowGraph cfg) {
-        for (Block block : cfg.getBlocks()) {
-            assert cfg.getBlocks()[block.getId()] == block;
-
-            for (Block pred : block.getPredecessors()) {
-                assert pred.getSuccessors().contains(block);
-                assert pred.getId() < block.getId() || pred.isLoopEnd();
-            }
-
-            for (Block sux : block.getSuccessors()) {
-                assert sux.getPredecessors().contains(block);
-                assert sux.getId() > block.getId() || sux.isLoopHeader();
-            }
-
-            if (block.getDominator() != null) {
-                assert block.getDominator().getId() < block.getId();
-                assert block.getDominator().getDominated().contains(block);
-            }
-            for (Block dominated : block.getDominated()) {
-                assert dominated.getId() > block.getId();
-                assert dominated.getDominator() == block;
-            }
-
-            assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().header == block;
-        }
-
-        if (cfg.getLoops() != null) {
-            for (Loop loop : cfg.getLoops()) {
-                assert loop.header.isLoopHeader();
-
-                for (Block block : loop.blocks) {
-                    assert block.getId() >= loop.header.getId();
-
-                    Loop blockLoop = block.getLoop();
-                    while (blockLoop != loop) {
-                        blockLoop = blockLoop.parent;
-                        assert blockLoop != null;
-                    }
-                }
-
-                for (Block block : loop.exits) {
-                    assert block.getId() >= loop.header.getId();
-
-                    Loop blockLoop = block.getLoop();
-                    while (blockLoop != null) {
-                        blockLoop = blockLoop.parent;
-                        assert blockLoop != loop;
-                    }
-                }
-            }
-        }
-
-        return true;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/ControlFlowGraph.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,302 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.cfg;
-
-import java.util.*;
-
-import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.nodes.*;
-
-public class ControlFlowGraph {
-
-    public final StructuredGraph graph;
-
-    private final NodeMap<Block> nodeToBlock;
-    private Block[] reversePostOrder;
-    private Loop[] loops;
-
-    public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) {
-        ControlFlowGraph cfg = new ControlFlowGraph(graph);
-        cfg.identifyBlocks();
-        if (connectBlocks || computeLoops || computeDominators || computePostdominators) {
-            cfg.connectBlocks();
-        }
-        if (computeLoops) {
-            cfg.computeLoopInformation();
-        }
-        if (computeDominators) {
-            cfg.computeDominators();
-        }
-        if (computePostdominators) {
-            cfg.computePostdominators();
-        }
-        assert CFGVerifier.verify(cfg);
-        return cfg;
-    }
-
-    protected ControlFlowGraph(StructuredGraph graph) {
-        this.graph = graph;
-        this.nodeToBlock = graph.createNodeMap();
-    }
-
-    public Block[] getBlocks() {
-        return reversePostOrder;
-    }
-
-    public Block getStartBlock() {
-        return reversePostOrder[0];
-    }
-
-    public NodeMap<Block> getNodeToBlock() {
-        return nodeToBlock;
-    }
-
-    public Block blockFor(Node node) {
-        return nodeToBlock.get(node);
-    }
-
-    public Loop[] getLoops() {
-        return loops;
-    }
-
-    private void identifyBlocks() {
-        // Find all block headers
-        int numBlocks = 0;
-        for (Node node : graph.getNodes()) {
-            if (node instanceof BeginNode) {
-                Block block = new Block();
-                numBlocks++;
-
-                block.beginNode = (BeginNode) node;
-                Node cur = node;
-                do {
-                    assert !cur.isDeleted();
-                    block.endNode = cur;
-
-                    assert nodeToBlock.get(cur) == null;
-                    nodeToBlock.set(cur, block);
-                    if (cur instanceof MergeNode) {
-                        for (PhiNode phi : ((MergeNode) cur).phis()) {
-                            nodeToBlock.set(phi, block);
-                        }
-                    }
-
-                    if (cur instanceof FixedNode) {
-                        double probability = ((FixedNode) cur).probability();
-                        if (probability > block.probability) {
-                            block.probability = probability;
-                        }
-                    }
-
-                    Node next = null;
-                    for (Node sux : cur.successors()) {
-                        if (sux != null && !(sux instanceof BeginNode)) {
-                            assert next == null;
-                            next = sux;
-                        }
-                    }
-                    cur = next;
-                } while (cur != null);
-            }
-        }
-
-        // Compute reverse postorder.
-        reversePostOrder = new Block[numBlocks];
-        int reversePostOrderId = numBlocks - 1;
-
-        ArrayList<Block> stack = new ArrayList<>();
-        stack.add(blockFor(graph.start()));
-
-        do {
-            Block block = stack.get(stack.size() - 1);
-            if (block.id == -1) {
-                // First time we see this block: push all successors.
-                for (Node suxNode : block.getEndNode().cfgSuccessors()) {
-                    Block suxBlock = blockFor(suxNode);
-                    if (suxBlock.id < 0) {
-                        stack.add(suxBlock);
-                    }
-                }
-                block.id = -2;
-            } else {
-                // Second time we see this block: All successors haved been processed, so insert block into reverse postorder list.
-                assert block.id == -2;
-                stack.remove(stack.size() - 1);
-                block.id = reversePostOrderId;
-                reversePostOrder[reversePostOrderId] = block;
-                reversePostOrderId--;
-            }
-        } while (!stack.isEmpty());
-        assert reversePostOrderId == -1;
-    }
-
-    // Connect blocks (including loop backward edges).
-    private void connectBlocks() {
-        for (Block block : reversePostOrder) {
-            List<Block> predecessors = new ArrayList<>();
-            for (Node predNode : block.getBeginNode().cfgPredecessors()) {
-                predecessors.add(nodeToBlock.get(predNode));
-            }
-            if (block.getBeginNode() instanceof LoopBeginNode) {
-                predecessors.add(nodeToBlock.get(((LoopBeginNode) block.getBeginNode()).loopEnd()));
-            }
-            block.predecessors = predecessors;
-
-            List<Block> successors = new ArrayList<>();
-            for (Node suxNode : block.getEndNode().cfgSuccessors()) {
-                successors.add(nodeToBlock.get(suxNode));
-            }
-            if (block.getEndNode() instanceof LoopEndNode) {
-                successors.add(nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin()));
-            }
-            block.successors = successors;
-        }
-    }
-
-    private void computeLoopInformation() {
-        List<Loop> loopsList = new ArrayList<>();
-        for (Block block : reversePostOrder) {
-            Node beginNode = block.getBeginNode();
-            if (beginNode instanceof LoopBeginNode) {
-                Loop loop = new Loop(block.getLoop(), loopsList.size(), block);
-                loopsList.add(loop);
-
-                LoopEndNode end = ((LoopBeginNode) beginNode).loopEnd();
-                Block endBlock = nodeToBlock.get(end);
-                computeLoopBlocks(endBlock, loop);
-            }
-        }
-        loops = loopsList.toArray(new Loop[loopsList.size()]);
-
-        for (Loop loop : loops) {
-            for (Block block : loop.blocks) {
-                for (Block sux : block.getSuccessors()) {
-                    if (sux.getLoopDepth() < loop.depth) {
-                        loop.exits.add(sux);
-                    }
-                }
-            }
-        }
-    }
-
-    private void computeLoopBlocks(Block block, Loop loop) {
-        if (block.getLoop() == loop) {
-            return;
-        }
-        assert block.loop == loop.parent;
-        block.loop = loop;
-
-        assert !loop.blocks.contains(block);
-        loop.blocks.add(block);
-
-        if (block != loop.header) {
-            for (Block pred : block.getPredecessors()) {
-                computeLoopBlocks(pred, loop);
-            }
-        }
-    }
-
-    private void computeDominators() {
-        assert reversePostOrder[0].getPredecessors().size() == 0 : "start block has no predecessor and therefore no dominator";
-        for (int i = 1; i < reversePostOrder.length; i++) {
-            Block block = reversePostOrder[i];
-            List<Block> predecessors = block.getPredecessors();
-            assert predecessors.size() > 0;
-
-            if (block.isLoopHeader()) {
-                // Loop headers have exactly one non-loop predecessor, and that is the dominator.
-                setDominator(block, predecessors.get(0));
-                continue;
-            }
-
-            Block dominator = predecessors.get(0);
-            for (int j = 1; j < predecessors.size(); j++) {
-                Block pred = predecessors.get(j);
-                dominator = commonDominator(dominator, pred);
-            }
-            setDominator(block, dominator);
-        }
-    }
-
-    private static void setDominator(Block block, Block dominator) {
-        block.dominator = dominator;
-        if (dominator.dominated == null) {
-            dominator.dominated = new ArrayList<>();
-        }
-        dominator.dominated.add(block);
-    }
-
-    public static Block commonDominator(Block a, Block b) {
-        Block iterA = a;
-        Block iterB = b;
-        while (iterA != iterB) {
-            if (iterA.getId() > iterB.getId()) {
-                iterA = iterA.getDominator();
-            } else {
-                assert iterB.getId() > iterA.getId();
-                iterB = iterB.getDominator();
-            }
-        }
-        return iterA;
-    }
-
-    private void computePostdominators() {
-        for (Block block : reversePostOrder) {
-            if (block.isLoopEnd()) {
-                // We do not want the loop header registered as the postdominator of the loop end.
-                continue;
-            }
-            Block postdominator = null;
-            for (Block sux : block.getSuccessors()) {
-                if (sux.isExceptionEntry()) {
-                    // We ignore exception handlers.
-                } else if (postdominator == null) {
-                    postdominator = sux;
-                } else {
-                    postdominator = commonPostdominator(postdominator, sux);
-                }
-            }
-            block.postdominator = postdominator;
-        }
-    }
-
-    private static Block commonPostdominator(Block a, Block b) {
-        Block iterA = a;
-        Block iterB = b;
-        while (iterA != iterB) {
-            if (iterA.getId() < iterB.getId()) {
-                iterA = iterA.getPostdominator();
-                if (iterA == null) {
-                    return null;
-                }
-            } else {
-                assert iterB.getId() < iterA.getId();
-                iterB = iterB.getPostdominator();
-                if (iterB == null) {
-                    return null;
-                }
-            }
-        }
-        return iterA;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Loop.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.cfg;
-
-import java.util.*;
-
-public class Loop {
-    public final Loop parent;
-    public final List<Loop> children;
-
-    public final int depth;
-    public final int index;
-    public final Block header;
-    public final List<Block> blocks;
-    public final List<Block> exits;
-
-    protected Loop(Loop parent, int index, Block header) {
-        this.parent = parent;
-        if (parent != null) {
-            this.depth = parent.depth + 1;
-            parent.children.add(this);
-        } else {
-            this.depth = 1;
-        }
-        this.index = index;
-        this.header = header;
-        this.blocks = new ArrayList<>();
-        this.children = new ArrayList<>();
-        this.exits = new ArrayList<>();
-    }
-
-    @Override
-    public String toString() {
-        return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : "");
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java	Wed Feb 08 21:15:00 2012 -0800
@@ -27,8 +27,8 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.graal.compiler.gen.LIRGenerator.LockScope;
-import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.virtual.*;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Feb 08 21:15:00 2012 -0800
@@ -26,7 +26,7 @@
 import static com.oracle.max.cri.ci.CiValue.*;
 import static com.oracle.max.cri.ci.CiValueUtil.*;
 import static com.oracle.max.cri.util.MemoryBarriers.*;
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
+import static com.oracle.max.graal.lir.ValueUtil.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -46,12 +46,12 @@
 import com.oracle.max.cri.xir.*;
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.StandardOp.ParametersOp;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.StandardOp.*;
+import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction;
 import com.oracle.max.graal.nodes.PhiNode.PhiType;
@@ -130,7 +130,9 @@
     /**
      * Mapping from blocks to the lock state at the end of the block, indexed by the id number of the block.
      */
-    private LockScope[] blockLocks;
+    private BlockMap<LockScope> blockLocks;
+
+    private BlockMap<FrameState> blockLastState;
 
     /**
      * The list of currently locked monitors.
@@ -149,7 +151,8 @@
         this.xir = xir;
         this.xirSupport = new XirSupport();
         this.debugInfoBuilder = new DebugInfoBuilder(nodeOperands);
-        this.blockLocks = new LockScope[lir.linearScanOrder().size()];
+        this.blockLocks = new BlockMap<>(lir.cfg);
+        this.blockLastState = new BlockMap<>(lir.cfg);
     }
 
     @Override
@@ -157,14 +160,6 @@
         return target;
     }
 
-    private LockScope locksFor(Block block) {
-        return blockLocks[block.getId()];
-    }
-
-    private void setLocksFor(Block block, LockScope locks) {
-        blockLocks[block.getId()] = locks;
-    }
-
     /**
      * Returns the operand that has been previously initialized by {@link #setResult()}
      * with the result of an instruction.
@@ -196,7 +191,7 @@
             case Double:
                 return new Variable(stackKind, lir.nextVariable(), CiRegister.RegisterFlag.FPU);
             default:
-                throw Util.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -300,7 +295,21 @@
         assert block.lir == null : "LIR list already computed for this block";
         block.lir = new ArrayList<>();
 
-        emitLabel(new Label(), block.align);
+        if (GraalOptions.AllocSSA && block.getBeginNode() instanceof MergeNode) {
+            assert phiValues.isEmpty();
+            MergeNode merge = (MergeNode) block.getBeginNode();
+            for (PhiNode phi : merge.phis()) {
+                if (phi.type() == PhiType.Value) {
+                    CiValue phiValue = newVariable(phi.kind());
+                    setResult(phi, phiValue);
+                    phiValues.add(phiValue);
+                }
+            }
+            append(new PhiLabelOp(new Label(), block.align, phiValues.toArray(new CiValue[phiValues.size()])));
+            phiValues.clear();
+        } else {
+            append(new LabelOp(new Label(), block.align));
+        }
 
         if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
             TTY.println("BEGIN Generating LIR for block B" + block.getId());
@@ -308,7 +317,7 @@
 
         curLocks = null;
         for (Block pred : block.getPredecessors()) {
-            LockScope predLocks = locksFor(pred);
+            LockScope predLocks = blockLocks.get(pred);
             if (curLocks == null) {
                 curLocks = predLocks;
             } else if (curLocks != predLocks && (!pred.isLoopEnd() || predLocks != null)) {
@@ -326,8 +335,8 @@
 
             for (Block pred : block.getPredecessors()) {
                 if (fs == null) {
-                    fs = pred.lastState;
-                } else if (fs != pred.lastState) {
+                    fs = blockLastState.get(pred);
+                } else if (fs != blockLastState.get(pred)) {
                     fs = null;
                     break;
                 }
@@ -345,10 +354,6 @@
             lastState = fs;
         }
 
-        if (GraalOptions.AllocSSA && block.getBeginNode() instanceof MergeNode) {
-            block.phis = new LIRPhiMapping(block, this);
-        }
-
         List<Node> nodes = lir.nodesFor(block);
         for (int i = 0; i < nodes.size(); i++) {
             Node instr = nodes.get(i);
@@ -406,8 +411,8 @@
             TTY.println("END Generating LIR for block B" + block.getId());
         }
 
-        setLocksFor(currentBlock, curLocks);
-        block.lastState = lastState;
+        blockLocks.put(currentBlock, curLocks);
+        blockLastState.put(block, lastState);
         currentBlock = null;
 
         if (GraalOptions.PrintIRWithLIR) {
@@ -665,27 +670,65 @@
 
     @Override
     public void visitMerge(MergeNode x) {
-        if (x.next() instanceof LoopBeginNode) {
-            moveToPhi((LoopBeginNode) x.next(), x);
-        }
     }
 
     @Override
     public void visitEndNode(EndNode end) {
-        assert end.merge() != null;
         moveToPhi(end.merge(), end);
-        emitJump(getLIRBlock(end.merge()), null);
     }
 
     @Override
     public void visitLoopEnd(LoopEndNode x) {
-        moveToPhi(x.loopBegin(), x);
         if (GraalOptions.GenLoopSafepoints && x.hasSafepointPolling()) {
             emitSafepointPoll(x);
         }
-        emitJump(getLIRBlock(x.loopBegin()), null);
+        moveToPhi(x.loopBegin(), x);
     }
 
+    private ArrayList<CiValue> phiValues = new ArrayList<>();
+
+    private void moveToPhi(MergeNode merge, FixedNode pred) {
+        if (GraalOptions.AllocSSA) {
+            assert phiValues.isEmpty();
+            for (PhiNode phi : merge.phis()) {
+                if (phi.type() == PhiType.Value) {
+                    phiValues.add(operand(phi.valueAt(pred)));
+                }
+            }
+            append(new PhiJumpOp(getLIRBlock(merge), phiValues.toArray(new CiValue[phiValues.size()])));
+            phiValues.clear();
+            return;
+        }
+
+        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+            TTY.println("MOVE TO PHI from " + pred + " to " + merge);
+        }
+        PhiResolver resolver = new PhiResolver(this);
+        for (PhiNode phi : merge.phis()) {
+            if (phi.type() == PhiType.Value) {
+                ValueNode curVal = phi.valueAt(pred);
+                resolver.move(operand(curVal), operandForPhi(phi));
+            }
+        }
+        resolver.dispose();
+
+        append(new JumpOp(getLIRBlock(merge), null));
+    }
+
+    private CiValue operandForPhi(PhiNode phi) {
+        assert phi.type() == PhiType.Value : "wrong phi type: " + phi;
+        CiValue result = operand(phi);
+        if (result == null) {
+            // allocate a variable for this phi
+            Variable newOperand = newVariable(phi.kind());
+            setResult(phi, newOperand);
+            return newOperand;
+        } else {
+            return result;
+        }
+    }
+
+
     public void emitSafepointPoll(FixedNode x) {
         if (!lastState.method().noSafepointPolls()) {
             XirSnippet snippet = xir.genSafepointPoll(site(x));
@@ -727,7 +770,7 @@
         } else if (node instanceof IsTypeNode) {
             emitTypeBranch((IsTypeNode) node, trueSuccessor, falseSuccessor, info);
         } else {
-            throw Util.unimplemented(node.toString());
+            throw GraalInternalError.unimplemented(node.toString());
         }
     }
 
@@ -789,7 +832,7 @@
         } else if (node instanceof ConstantNode) {
             return emitConstantConditional(((ConstantNode) node).asConstant().asBoolean(), trueValue, falseValue);
         } else {
-            throw Util.unimplemented(node.toString());
+            throw GraalInternalError.unimplemented(node.toString());
         }
     }
 
@@ -921,7 +964,7 @@
             } else if (isStackSlot(value)) {
                 return CiStackSlot.get(value.kind.stackKind(), asStackSlot(value).rawOffset(), asStackSlot(value).rawAddFrameSize());
             } else {
-                throw Util.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
             }
         }
         return value;
@@ -945,7 +988,7 @@
                 argList.add(operand);
 
             } else {
-                throw Util.shouldNotReachHere("I thought we no longer have null entries for two-slot types...");
+                throw GraalInternalError.shouldNotReachHere("I thought we no longer have null entries for two-slot types...");
             }
         }
         return argList;
@@ -1127,40 +1170,6 @@
     }
 
 
-
-    private void moveToPhi(MergeNode merge, FixedNode pred) {
-        if (GraalOptions.AllocSSA) {
-            return;
-        }
-
-        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
-            TTY.println("MOVE TO PHI from " + pred + " to " + merge);
-        }
-        PhiResolver resolver = new PhiResolver(this);
-        for (PhiNode phi : merge.phis()) {
-            if (phi.type() == PhiType.Value) {
-                ValueNode curVal = phi.valueAt(pred);
-                resolver.move(operand(curVal), operandForPhi(phi));
-            }
-        }
-        resolver.dispose();
-    }
-
-    private CiValue operandForPhi(PhiNode phi) {
-        assert phi.type() == PhiType.Value : "wrong phi type: " + phi;
-        CiValue result = operand(phi);
-        if (result == null) {
-            // allocate a variable for this phi
-            Variable newOperand = newVariable(phi.kind());
-            setResult(phi, newOperand);
-            return newOperand;
-        } else {
-            return result;
-        }
-    }
-
-
-
     protected XirArgument toXirArgument(CiValue v) {
         if (v == null) {
             return null;
@@ -1185,7 +1194,7 @@
         } else if (op instanceof XirTemp) {
             return newVariable(op.kind);
         } else {
-            Util.shouldNotReachHere();
+            GraalInternalError.shouldNotReachHere();
             return null;
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiResolver.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiResolver.java	Wed Feb 08 21:15:00 2012 -0800
@@ -23,7 +23,7 @@
 package com.oracle.max.graal.compiler.gen;
 
 import static com.oracle.max.cri.ci.CiValue.*;
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
+import static com.oracle.max.graal.lir.ValueUtil.*;
 
 import java.util.*;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/FrameMap.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,344 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.lir;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ci.CiCallingConvention.Type;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.compiler.util.*;
-
-/**
- * This class is used to build the stack frame layout for a compiled method.
- * A {@link CiStackSlot} is used to index slots of the frame relative to the stack pointer.
- * The frame size is only fixed after register allocation when all spill slots have
- * been allocated. Both the outgoing argument area and the spill are can grow until then.
- * Therefore, outgoing arguments are indexed from the stack pointer, while spill slots
- * are indexed from the beginning of the frame (and the total frame size has to be added
- * to get the actual offset from the stack pointer).
- * <br>
- * This is the format of a stack frame:
- * <pre>
- *   Base       Contents
- *
- *            :                                :  -----
- *   caller   | incoming overflow argument n   |    ^
- *   frame    :     ...                        :    | positive
- *            | incoming overflow argument 0   |    | offsets
- *   ---------+--------------------------------+---------------------
- *            | return address                 |    |            ^
- *   current  +--------------------------------+    |            |    -----
- *   frame    |                                |    |            |      ^
- *            : callee save area               :    |            |      |
- *            |                                |    |            |      |
- *            +--------------------------------+    |            |      |
- *            | spill slot 0                   |    | negative   |      |
- *            :     ...                        :    v offsets    |      |
- *            | spill slot n                   |  -----        total  frame
- *            +--------------------------------+               frame  size
- *            | alignment padding              |               size     |
- *            +--------------------------------+  -----          |      |
- *            | outgoing overflow argument n   |    ^            |      |
- *            :     ...                        :    | positive   |      |
- *            | outgoing overflow argument 0   |    | offsets    v      v
- *    %sp-->  +--------------------------------+---------------------------
- *
- * </pre>
- * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size
- * of such a block may be greater than the size of a normal spill slot or the word size.
- * <br>
- * A runtime has two ways to reserve space in the stack frame for its own use: <ul>
- * <li>A memory block somewhere in the frame of size {@link RiRuntime#getCustomStackAreaSize()}. The offset
- *     to this block is returned in {@link CiTargetMethod#customStackAreaOffset()}.
- * <li>At the beginning of the overflow argument area: The calling convention can specify that the first
- *     overflow stack argument is not at offset 0, but at a specified offset o. Use
- *     {@link RiRuntime#getMinimumOutgoingSize()} to make sure that call-free methods also have this space
- *     reserved. Then the VM can use memory the memory at offset 0 relative to the stack pointer.
- * </ul>
- */
-public final class FrameMap {
-    public final RiRuntime runtime;
-    public final CiTarget target;
-    public final RiRegisterConfig registerConfig;
-
-    /**
-     * The final frame size, not including the size of the return address.
-     * The value is only set after register allocation is complete, i.e., after all spill slots have been allocated.
-     */
-    private int frameSize;
-
-    /**
-     * Size of the area occupied by spill slots and other stack-allocated memory blocks.
-     */
-    private int spillSize;
-
-    /**
-     * Size of the area occupied by outgoing overflow arguments.
-     * This value is adjusted as calling conventions for outgoing calls are retrieved.
-     */
-    private int outgoingSize;
-
-    /**
-     * The list of stack areas allocated in this frame that are present in every reference map.
-     */
-    private final List<CiStackSlot> objectStackBlocks;
-
-    /**
-     * The stack area reserved for use by the VM, or {@code null} if the VM does not request stack space.
-     */
-    private final CiStackSlot customArea;
-
-    /**
-     * Creates a new frame map for the specified method.
-     */
-    public FrameMap(RiRuntime runtime, CiTarget target, RiRegisterConfig registerConfig) {
-        this.runtime = runtime;
-        this.target = target;
-        this.registerConfig = registerConfig;
-        this.frameSize = -1;
-        this.spillSize = returnAddressSize() + calleeSaveAreaSize();
-        this.outgoingSize = runtime.getMinimumOutgoingSize();
-        this.objectStackBlocks = new ArrayList<>();
-        this.customArea = allocateStackBlock(runtime.getCustomStackAreaSize(), false);
-    }
-
-
-    private int returnAddressSize() {
-        return target.arch.returnAddressSize;
-    }
-
-    private int calleeSaveAreaSize() {
-        CiCalleeSaveLayout csl = registerConfig.getCalleeSaveLayout();
-        return csl != null ? csl.size : 0;
-    }
-
-    /**
-     * Gets the frame size of the compiled frame, not including the size of the return address.
-     * @return The size of the frame (in bytes).
-     */
-    public int frameSize() {
-        assert frameSize != -1 : "frame size not computed yet";
-        return frameSize;
-    }
-
-    /**
-     * Gets the total frame size of the compiled frame, including the size of the return address.
-     * @return The total size of the frame (in bytes).
-     */
-    public int totalFrameSize() {
-        return frameSize() + returnAddressSize();
-    }
-
-    /**
-     * Sets the frame size for this frame.
-     * @param frameSize The frame size (in bytes).
-     */
-    public void setFrameSize(int frameSize) {
-        assert this.frameSize == -1 : "must only be set once";
-        this.frameSize = frameSize;
-    }
-
-    /**
-     * Computes the frame size for this frame. After this method has been called, methods that change the
-     * frame size cannot be called anymore, e.g., no more spill slots or outgoing arguments can be requested.
-     */
-    public void finish() {
-        setFrameSize(target.alignFrameSize(outgoingSize + spillSize - returnAddressSize()));
-    }
-
-    /**
-     * Computes the offset of a stack slot relative to the frame register.
-     * This is also the bit index of stack slots in the reference map.
-     *
-     * @param slot a stack slot
-     * @return the offset of the stack slot
-     */
-    public int offsetForStackSlot(CiStackSlot slot) {
-        assert (!slot.rawAddFrameSize() && slot.rawOffset() < outgoingSize) ||
-            (slot.rawAddFrameSize() && slot.rawOffset() < 0 && -slot.rawOffset() <= spillSize) ||
-            (slot.rawAddFrameSize() && slot.rawOffset() >= 0);
-        return slot.offset(totalFrameSize());
-    }
-
-    /**
-     * Gets the offset to the stack area where callee-saved registers are stored.
-     * @return The offset to the callee save area (in bytes).
-     */
-    public int offsetToCalleeSaveArea() {
-        return frameSize() - calleeSaveAreaSize();
-    }
-
-    /**
-     * Gets the offset of the stack area stack block reserved for use by the VM, or -1 if the VM does not request stack space.
-     * @return The offset to the custom area (in bytes).
-     */
-    public int offsetToCustomArea() {
-        return customArea == null ? -1 : offsetForStackSlot(customArea);
-    }
-
-    /**
-     * Informs the frame map that the compiled code calls a particular method, which
-     * may need stack space for outgoing arguments.
-     * @param cc The calling convention for the called method.
-     * @param type The type of calling convention.
-     */
-    public void callsMethod(CiCallingConvention cc, Type type) {
-        // TODO look at the actual stack offsets?
-        assert type.out;
-        reserveOutgoing(cc.stackSize);
-    }
-
-    /**
-     * Reserves space for stack-based outgoing arguments.
-     * @param argsSize The amount of space (in bytes) to reserve for stack-based outgoing arguments.
-     */
-    public void reserveOutgoing(int argsSize) {
-        assert frameSize == -1 : "frame size must not yet be fixed";
-        outgoingSize = Math.max(outgoingSize, argsSize);
-    }
-
-    private CiStackSlot getSlot(CiKind kind, int additionalOffset) {
-        return CiStackSlot.get(kind, -spillSize + additionalOffset, true);
-    }
-
-    /**
-     * Reserves a spill slot in the frame of the method being compiled. The returned slot is aligned on its natural alignment,
-     * i.e., an 8-byte spill slot is aligned at an 8-byte boundary.
-     * @param kind The kind of the spill slot to be reserved.
-     * @return A spill slot denoting the reserved memory area.
-     */
-    public CiStackSlot allocateSpillSlot(CiKind kind) {
-        assert frameSize == -1 : "frame size must not yet be fixed";
-        int size = target.sizeInBytes(kind);
-        spillSize = Util.roundUp(spillSize + size, size);
-        return getSlot(kind, 0);
-    }
-
-    /**
-     * Reserves a block of memory in the frame of the method being compiled. The returned block is aligned on a word boundary.
-     * If the requested size is 0, the method returns {@code null}.
-     *
-     * @param size The size to reserve (in bytes).
-     * @param refs Specifies if the block is all references. If true, the block will be in all reference maps for this method.
-     *             The caller is responsible to initialize the memory block before the first instruction that uses a reference map.
-     * @return A stack slot describing the begin of the memory block.
-     */
-    public CiStackSlot allocateStackBlock(int size, boolean refs) {
-        assert frameSize == -1 : "frame size must not yet be fixed";
-        if (size == 0) {
-            return null;
-        }
-        spillSize = Util.roundUp(spillSize + size, target.wordSize);
-
-        if (refs) {
-            assert size % target.wordSize == 0;
-            CiStackSlot result = getSlot(CiKind.Object, 0);
-            objectStackBlocks.add(result);
-            for (int i = target.wordSize; i < size; i += target.wordSize) {
-                objectStackBlocks.add(getSlot(CiKind.Object, i));
-            }
-            return result;
-
-        } else {
-            return getSlot(target.wordKind, 0);
-        }
-    }
-
-
-    private int frameRefMapIndex(CiStackSlot slot) {
-        assert offsetForStackSlot(slot) % target.wordSize == 0;
-        return offsetForStackSlot(slot) / target.wordSize;
-    }
-
-    /**
-     * Initializes a reference map that covers all registers of the target architecture.
-     */
-    public CiBitMap initRegisterRefMap() {
-        return new CiBitMap(target.arch.registerReferenceMapBitCount);
-    }
-
-    /**
-     * Initializes a reference map. Initially, the size is large enough to cover all the
-     * slots in the frame. If the method has incoming reference arguments on the stack,
-     * the reference map might grow later when such a reference is set.
-     */
-    public CiBitMap initFrameRefMap() {
-        CiBitMap frameRefMap = new CiBitMap(frameSize() / target.wordSize);
-        for (CiStackSlot slot : objectStackBlocks) {
-            setReference(slot, null, frameRefMap);
-        }
-        return frameRefMap;
-    }
-
-    /**
-     * Marks the specified location as a reference in the reference map of the debug information.
-     * The tracked location can be a {@link CiRegisterValue} or a {@link CiStackSlot}. Note that a
-     * {@link CiConstant} is automatically tracked.
-     *
-     * @param location The location to be added to the reference map.
-     * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}.
-     * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}.
-     */
-    public void setReference(CiValue location, CiBitMap registerRefMap, CiBitMap frameRefMap) {
-        if (location.kind == CiKind.Object) {
-            if (isRegister(location)) {
-                assert registerRefMap.size() == target.arch.registerReferenceMapBitCount;
-                registerRefMap.set(asRegister(location).number);
-            } else if (isStackSlot(location)) {
-                int index = frameRefMapIndex(asStackSlot(location));
-                frameRefMap.grow(index + 1);
-                frameRefMap.set(index);
-            } else {
-                assert isConstant(location);
-            }
-        }
-    }
-
-    /**
-     * Clears the specified location as a reference in the reference map of the debug information.
-     * The tracked location can be a {@link CiRegisterValue} or a {@link CiStackSlot}. Note that a
-     * {@link CiConstant} is automatically tracked.
-     *
-     * @param location The location to be removed from the reference map.
-     * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}.
-     * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}.
-     */
-    public void clearReference(CiValue location, CiBitMap registerRefMap, CiBitMap frameRefMap) {
-        if (location.kind == CiKind.Object) {
-            if (location instanceof CiRegisterValue) {
-                assert registerRefMap.size() == target.arch.registerReferenceMapBitCount;
-                registerRefMap.clear(asRegister(location).number);
-            } else if (isStackSlot(location)) {
-                int index = frameRefMapIndex(asStackSlot(location));
-                if (index < frameRefMap.size()) {
-                    frameRefMap.clear(index);
-                }
-            } else {
-                assert isConstant(location);
-            }
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIR.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.lir;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.graph.*;
-
-/**
- * This class implements the overall container for the LIR graph
- * and directs its construction, optimization, and finalization.
- */
-public class LIR {
-
-    public final ControlFlowGraph cfg;
-
-    /**
-     * The nodes for the blocks.
-     * TODO: This should go away, we want all nodes connected with a next-pointer.
-     */
-    private final BlockMap<List<Node>> nodesFor;
-
-    /**
-     * The linear-scan ordered list of blocks.
-     */
-    private final List<Block> linearScanOrder;
-
-    /**
-     * The order in which the code is emitted.
-     */
-    private final List<Block> codeEmittingOrder;
-
-
-    public final List<SlowPath> slowPaths;
-
-    public final List<SlowPath> deoptimizationStubs;
-
-    /**
-     * The last slow path emitted, which can be used emit marker bytes.
-     */
-    public SlowPath methodEndMarker;
-
-    private int numVariables;
-
-    public SpillMoveFactory spillMoveFactory;
-
-    public interface SpillMoveFactory {
-        LIRInstruction createMove(CiValue result, CiValue input);
-        LIRInstruction createExchange(CiValue input1, CiValue input2);
-    }
-
-    public interface SlowPath {
-        void emitCode(TargetMethodAssembler tasm);
-    }
-
-    /**
-     * Creates a new LIR instance for the specified compilation.
-     * @param numLoops number of loops
-     * @param compilation the compilation
-     */
-    public LIR(ControlFlowGraph cfg, BlockMap<List<Node>> nodesFor, List<Block> linearScanOrder, List<Block> codeEmittingOrder) {
-        this.cfg = cfg;
-        this.nodesFor = nodesFor;
-        this.codeEmittingOrder = codeEmittingOrder;
-        this.linearScanOrder = linearScanOrder;
-
-        slowPaths = new ArrayList<>();
-        deoptimizationStubs = new ArrayList<>();
-    }
-
-    public List<Node> nodesFor(Block block) {
-        return nodesFor.get(block);
-    }
-
-    /**
-     * Gets the linear scan ordering of blocks as a list.
-     * @return the blocks in linear scan order
-     */
-    public List<Block> linearScanOrder() {
-        return linearScanOrder;
-    }
-
-    public List<Block> codeEmittingOrder() {
-        return codeEmittingOrder;
-    }
-
-    public int numVariables() {
-        return numVariables;
-    }
-
-    public int nextVariable() {
-        return numVariables++;
-    }
-
-    public void emitCode(TargetMethodAssembler tasm) {
-        if (GraalOptions.PrintLIR && !TTY.isSuppressed()) {
-            printLIR(codeEmittingOrder());
-        }
-
-        for (Block b : codeEmittingOrder()) {
-            emitBlock(tasm, b);
-        }
-
-        // generate code for slow cases
-        for (SlowPath sp : slowPaths) {
-            emitSlowPath(tasm, sp);
-        }
-        // generate deoptimization stubs
-        for (SlowPath sp : deoptimizationStubs) {
-            emitSlowPath(tasm, sp);
-        }
-        // generate traps at the end of the method
-        emitSlowPath(tasm, methodEndMarker);
-    }
-
-    private void emitBlock(TargetMethodAssembler tasm, Block block) {
-        if (GraalOptions.PrintLIRWithAssembly) {
-            TTY.println(block.toString());
-        }
-
-        if (GraalOptions.CommentedAssembly) {
-            tasm.blockComment(String.format("block B%d %s", block.getId(), block.getLoop()));
-        }
-
-        for (LIRInstruction op : block.lir) {
-            if (GraalOptions.CommentedAssembly) {
-                tasm.blockComment(String.format("%d %s", op.id(), op));
-            }
-            if (GraalOptions.PrintLIRWithAssembly && !TTY.isSuppressed()) {
-                // print out the LIR operation followed by the resulting assembly
-                TTY.println(op.toStringWithIdPrefix());
-                TTY.println();
-            }
-
-            emitOp(tasm, op);
-
-            if (GraalOptions.PrintLIRWithAssembly) {
-                printAssembly(tasm);
-            }
-        }
-    }
-
-    private static void emitOp(TargetMethodAssembler tasm, LIRInstruction op) {
-        try {
-            try {
-                op.emitCode(tasm);
-            } catch (AssertionError t) {
-                throw new GraalInternalError(t);
-            } catch (RuntimeException t) {
-                throw new GraalInternalError(t);
-            }
-        } catch (GraalInternalError e) {
-            throw e.addContext("lir instruction", op);
-        }
-    }
-
-    private static void emitSlowPath(TargetMethodAssembler tasm, SlowPath sp) {
-        if (GraalOptions.CommentedAssembly) {
-            tasm.blockComment(String.format("slow case %s", sp.getClass().getName()));
-        }
-        sp.emitCode(tasm);
-    }
-
-    private int lastDecodeStart;
-
-    private void printAssembly(TargetMethodAssembler tasm) {
-        byte[] currentBytes = tasm.asm.codeBuffer.copyData(lastDecodeStart, tasm.asm.codeBuffer.position());
-        if (currentBytes.length > 0) {
-            String disasm = tasm.runtime.disassemble(currentBytes, lastDecodeStart);
-            if (disasm.length() != 0) {
-                TTY.println(disasm);
-            } else {
-                TTY.println("Code [+%d]: %d bytes", lastDecodeStart, currentBytes.length);
-                Util.printBytes(lastDecodeStart, currentBytes, GraalOptions.PrintAssemblyBytesPerLine);
-            }
-        }
-        lastDecodeStart = tasm.asm.codeBuffer.position();
-    }
-
-
-    public static void printBlock(Block x) {
-        // print block id
-        TTY.print("B%d ", x.getId());
-
-        // print flags
-        if (x.isLoopHeader()) {
-            TTY.print("lh ");
-        }
-        if (x.isLoopEnd()) {
-            TTY.print("le ");
-        }
-
-        // print block bci range
-        TTY.print("[%d, %d] ", -1, -1);
-
-        // print predecessors and successors
-        if (x.numberOfPreds() > 0) {
-            TTY.print("preds: ");
-            for (int i = 0; i < x.numberOfPreds(); i++) {
-                TTY.print("B%d ", x.predAt(i).getId());
-            }
-        }
-
-        if (x.numberOfSux() > 0) {
-            TTY.print("sux: ");
-            for (int i = 0; i < x.numberOfSux(); i++) {
-                TTY.print("B%d ", x.suxAt(i).getId());
-            }
-        }
-
-        TTY.println();
-    }
-
-    public static void printLIR(List<Block> blocks) {
-        if (TTY.isSuppressed()) {
-            return;
-        }
-        TTY.println("LIR:");
-        int i;
-        for (i = 0; i < blocks.size(); i++) {
-            Block bb = blocks.get(i);
-            printBlock(bb);
-            TTY.println("__id_Instruction___________________________________________");
-            for (LIRInstruction op : bb.lir) {
-                TTY.println(op.toStringWithIdPrefix());
-                TTY.println();
-            }
-            TTY.println();
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.lir;
-
-import static com.oracle.max.graal.compiler.lir.LIRInstruction.*;
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-
-/**
- * This class represents garbage collection and deoptimization information attached to a LIR instruction.
- */
-public class LIRDebugInfo {
-    public final CiFrame topFrame;
-    private final CiVirtualObject[] virtualObjects;
-    private final List<CiStackSlot> pointerSlots;
-    public final LabelRef exceptionEdge;
-    private CiDebugInfo debugInfo;
-
-    public LIRDebugInfo(CiFrame topFrame, CiVirtualObject[] virtualObjects, List<CiStackSlot> pointerSlots, LabelRef exceptionEdge) {
-        this.topFrame = topFrame;
-        this.virtualObjects = virtualObjects;
-        this.pointerSlots = pointerSlots;
-        this.exceptionEdge = exceptionEdge;
-    }
-
-    public boolean hasDebugInfo() {
-        return debugInfo != null;
-    }
-
-    public CiDebugInfo debugInfo() {
-        assert debugInfo != null : "debug info not allocated yet";
-        return debugInfo;
-    }
-
-    /**
-     * Iterates the frame state and calls the {@link ValueProcedure} for every variable.
-     *
-     * @param proc The procedure called for variables.
-     */
-    public void forEachState(ValueProcedure proc) {
-        for (CiFrame cur = topFrame; cur != null; cur = cur.caller()) {
-            processValues(cur.values, proc);
-        }
-        if (virtualObjects != null) {
-            for (CiVirtualObject obj : virtualObjects) {
-                processValues(obj.values(), proc);
-            }
-        }
-    }
-
-    /**
-     * We filter out constant and illegal values ourself before calling the procedure, so {@link OperandFlag#Constant} and {@link OperandFlag#Illegal} need not be set.
-     */
-    private static final EnumSet<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-
-    private void processValues(CiValue[] values, ValueProcedure proc) {
-        for (int i = 0; i < values.length; i++) {
-            CiValue value = values[i];
-            if (value instanceof CiMonitorValue) {
-                CiMonitorValue monitor = (CiMonitorValue) value;
-                if (processed(monitor.owner)) {
-                    monitor.owner = proc.doValue(monitor.owner, OperandMode.Alive, STATE_FLAGS);
-                }
-
-            } else if (processed(value)) {
-                values[i] = proc.doValue(value, OperandMode.Alive, STATE_FLAGS);
-            }
-        }
-    }
-
-    private boolean processed(CiValue value) {
-        if (isIllegal(value)) {
-            // Ignore dead local variables.
-            return false;
-        } else if (isConstant(value)) {
-            // Ignore constants, the register allocator does not need to see them.
-            return false;
-        } else if (isVirtualObject(value)) {
-            assert Arrays.asList(virtualObjects).contains(value);
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-
-    public void finish(CiBitMap registerRefMap, CiBitMap frameRefMap, FrameMap frameMap) {
-        debugInfo = new CiDebugInfo(topFrame, registerRefMap, frameRefMap);
-
-        // Add additional stack slots for outgoing method parameters.
-        if (pointerSlots != null) {
-            for (CiStackSlot v : pointerSlots) {
-                frameMap.setReference(v, registerRefMap, frameRefMap);
-            }
-        }
-    }
-
-
-    @Override
-    public String toString() {
-        return debugInfo != null ? debugInfo.toString() : topFrame.toString();
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,446 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.lir;
-
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.util.*;
-
-/**
- * The {@code LIRInstruction} class definition.
- */
-public abstract class LIRInstruction {
-
-    public static final CiValue[] NO_OPERANDS = {};
-
-    /**
-     * Iterator for iterating over a list of values. Subclasses must overwrite one of the doValue methods.
-     * Clients of the class must only call the doValue method that takes additional parameters.
-     */
-    public abstract static class ValueProcedure {
-        /**
-         * Iterator method to be overwritten. This version of the iterator does not take additional parameters
-         * to keep the signature short.
-         *
-         * @param value The value that is iterated.
-         * @return The new value to replace the value that was passed in.
-         */
-        protected CiValue doValue(CiValue value) {
-            throw Util.shouldNotReachHere("One of the doValue() methods must be overwritten");
-        }
-
-        /**
-         * Iterator method to be overwritten. This version of the iterator gets additional parameters about the
-         * processed value.
-         *
-         * @param value The value that is iterated.
-         * @param mode The operand mode for the value.
-         * @param flags A set of flags for the value.
-         * @return The new value to replace the value that was passed in.
-         */
-        public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
-            return doValue(value);
-        }
-    }
-
-
-    /**
-     * Constants denoting how a LIR instruction uses an operand.
-     */
-    public enum OperandMode {
-        /**
-         * The value must have been defined before. It is alive before the instruction until the beginning of the
-         * instruction, but not necessarily throughout the instruction. A register assigned to it can also be assigend
-         * to a Temp or Output operand. The value can be used again after the instruction, so the instruction must not
-         * modify the register.
-         */
-        Input,
-
-        /**
-         * The value must have been defined before. It is alive before the instruction and throughout the instruction. A
-         * register assigned to it cannot be assigned to a Temp or Output operand. The value can be used again after the
-         * instruction, so the instruction must not modify the register.
-         */
-        Alive,
-
-        /**
-         * The value must not have been defined before, and must not be used after the instruction. The instruction can
-         * do whatever it wants with the register assigned to it (or not use it at all).
-         */
-        Temp,
-
-        /**
-         * The value must not have been defined before. The instruction has to assign a value to the register. The
-         * value can (and most likely will) be used after the instruction.
-         */
-        Output,
-    }
-
-    /**
-     * Flags for an operand.
-     */
-    public enum OperandFlag {
-        /**
-         * The value can be a {@link CiRegisterValue}.
-         */
-        Register,
-
-        /**
-         * The value can be a {@link CiStackSlot}.
-         */
-        Stack,
-
-        /**
-         * The value can be a {@link CiAddress}.
-         */
-        Address,
-
-        /**
-         * The value can be a {@link CiConstant}.
-         */
-        Constant,
-
-        /**
-         * The value can be {@link CiValue#IllegalValue}.
-         */
-        Illegal,
-
-        /**
-         * The register allocator should try to assign a certain register to improve code quality.
-         * Use {@link LIRInstruction#forEachRegisterHint} to access the register hints.
-         */
-        RegisterHint,
-
-        /**
-         * The value can be uninitialized, e.g., a stack slot that has not written to before. This is only
-         * used to avoid false positives in verification code.
-         */
-        Uninitialized,
-    }
-
-    /**
-     * For validity checking of the operand flags defined by instruction subclasses.
-     */
-    private static final EnumMap<OperandMode, EnumSet<OperandFlag>> ALLOWED_FLAGS;
-
-    static {
-        ALLOWED_FLAGS = new EnumMap<>(OperandMode.class);
-        ALLOWED_FLAGS.put(OperandMode.Input,  EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Address, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint, OperandFlag.Uninitialized));
-        ALLOWED_FLAGS.put(OperandMode.Alive,  EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Address, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint, OperandFlag.Uninitialized));
-        ALLOWED_FLAGS.put(OperandMode.Temp,   EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint));
-        ALLOWED_FLAGS.put(OperandMode.Output, EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Illegal, OperandFlag.RegisterHint));
-    }
-
-    /**
-     * The opcode of this instruction.
-     */
-    protected final Object code;
-
-    /**
-     * The output operands for this instruction (modified by the register allocator).
-     */
-    protected final CiValue[] outputs;
-
-    /**
-     * The input operands for this instruction (modified by the register allocator).
-     */
-    protected final CiValue[] inputs;
-
-    /**
-     * The alive operands for this instruction (modified by the register allocator).
-     */
-    protected final CiValue[] alives;
-
-    /**
-     * The temp operands for this instruction (modified by the register allocator).
-     */
-    protected final CiValue[] temps;
-
-    /**
-     * Used to emit debug information.
-     */
-    public final LIRDebugInfo info;
-
-    /**
-     * Instruction id for register allocation.
-     */
-    private int id;
-
-    /**
-     * Constructs a new LIR instruction that has input and temp operands.
-     *
-     * @param opcode the opcode of the new instruction
-     * @param outputs the operands that holds the operation results of this instruction.
-     * @param info the {@link LIRDebugInfo} info that is to be preserved for the instruction. This will be {@code null} when no debug info is required for the instruction.
-     * @param inputs the input operands for the instruction.
-     * @param temps the temp operands for the instruction.
-     */
-    public LIRInstruction(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) {
-        this.code = opcode;
-        this.outputs = outputs;
-        this.inputs = inputs;
-        this.alives = alives;
-        this.temps = temps;
-        this.info = info;
-        this.id = -1;
-    }
-
-    public abstract void emitCode(TargetMethodAssembler tasm);
-
-
-    public final int id() {
-        return id;
-    }
-
-    public final void setId(int id) {
-        this.id = id;
-    }
-
-    /**
-     * Gets an input operand of this instruction.
-     *
-     * @param index the index of the operand requested.
-     * @return the {@code index}'th input operand.
-     */
-    protected final CiValue input(int index) {
-        return inputs[index];
-    }
-
-    /**
-     * Gets an alive operand of this instruction.
-     *
-     * @param index the index of the operand requested.
-     * @return the {@code index}'th alive operand.
-     */
-    protected final CiValue alive(int index) {
-        return alives[index];
-    }
-
-    /**
-     * Gets a temp operand of this instruction.
-     *
-     * @param index the index of the operand requested.
-     * @return the {@code index}'th temp operand.
-     */
-    protected final CiValue temp(int index) {
-        return temps[index];
-    }
-
-    /**
-     * Gets the result operand for this instruction.
-     *
-     * @return return the result operand
-     */
-    protected final CiValue output(int index) {
-        return outputs[index];
-    }
-
-    /**
-     * Gets the instruction name.
-     */
-    public String name() {
-        return code.toString();
-    }
-
-    public boolean hasOperands() {
-        return inputs.length > 0 || alives.length > 0 || temps.length > 0 || outputs.length > 0 || info != null || hasCall();
-    }
-
-    private static final EnumSet<OperandFlag> ADDRESS_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
-
-    private void forEach(CiValue[] values, OperandMode mode, ValueProcedure proc) {
-        for (int i = 0; i < values.length; i++) {
-            assert ALLOWED_FLAGS.get(mode).containsAll(flagsFor(mode, i));
-
-            CiValue value = values[i];
-            if (isAddress(value)) {
-                assert flagsFor(mode, i).contains(OperandFlag.Address);
-                CiAddress address = asAddress(value);
-                address.base = proc.doValue(address.base, mode, ADDRESS_FLAGS);
-                address.index = proc.doValue(address.index, mode, ADDRESS_FLAGS);
-            } else {
-                values[i] = proc.doValue(values[i], mode, flagsFor(mode, i));
-            }
-        }
-    }
-
-    public final void forEachInput(ValueProcedure proc) {
-        forEach(inputs, OperandMode.Input, proc);
-    }
-
-    public final void forEachAlive(ValueProcedure proc) {
-        forEach(alives, OperandMode.Alive, proc);
-    }
-
-    public final void forEachTemp(ValueProcedure proc) {
-        forEach(temps, OperandMode.Temp, proc);
-    }
-
-    public final void forEachOutput(ValueProcedure proc) {
-        forEach(outputs, OperandMode.Output, proc);
-    }
-
-    public final void forEachState(ValueProcedure proc) {
-        if (info != null) {
-            info.forEachState(proc);
-
-            if (this instanceof LIRXirInstruction) {
-                LIRXirInstruction xir = (LIRXirInstruction) this;
-                if (xir.infoAfter != null) {
-                    xir.infoAfter.forEachState(proc);
-                }
-            }
-        }
-    }
-
-    /**
-     * Returns true when this instruction is a call instruction that destroys all caller-saved registers.
-     */
-    public final boolean hasCall() {
-        return this instanceof StandardOp.CallOp;
-    }
-
-    /**
-     * Iterates all register hints for the specified value, i.e., all preferred candidates for the register to be
-     * assigned to the value.
-     * <br>
-     * Subclasses can override this method. The default implementation processes all Input operands as the hints for
-     * an Output operand, and all Output operands as the hints for an Input operand.
-     *
-     * @param value The value the hints are needed for.
-     * @param mode The operand mode of the value.
-     * @param proc The procedure invoked for all the hints. If the procedure returns a non-null value, the iteration is stopped
-     *             and the value is returned by this method, i.e., clients can stop the iteration once a suitable hint has been found.
-     * @return The non-null value returned by the procedure, or null.
-     */
-    public CiValue forEachRegisterHint(CiValue value, OperandMode mode, ValueProcedure proc) {
-        CiValue[] hints;
-        if (mode == OperandMode.Input) {
-            hints = outputs;
-        } else if (mode == OperandMode.Output) {
-            hints = inputs;
-        } else {
-            return null;
-        }
-
-        for (int i = 0; i < hints.length; i++) {
-            CiValue result = proc.doValue(hints[i], null, null);
-            if (result != null) {
-                return result;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Used by the register allocator to decide which kind of location can be assigned to the operand.
-     * @param mode The kind of operand.
-     * @param index The index of the operand.
-     * @return The flags for the operand.
-     */
-    // TODO this method will go away when we have named operands, the flags will be specified as annotations instead.
-    protected abstract EnumSet<OperandFlag> flagsFor(OperandMode mode, int index);
-
-    protected void verify() {
-    }
-
-
-    public final String toStringWithIdPrefix() {
-        if (id != -1) {
-            return String.format("%4d %s", id, toString());
-        }
-        return "     " + toString();
-    }
-
-    /**
-     * Gets the operation performed by this instruction in terms of its operands as a string.
-     */
-    public String operationString() {
-        StringBuilder buf = new StringBuilder();
-        String sep = "";
-        if (outputs.length > 1) {
-            buf.append("(");
-        }
-        for (CiValue output : outputs) {
-            buf.append(sep).append(output);
-            sep = ", ";
-        }
-        if (outputs.length > 1) {
-            buf.append(")");
-        }
-        if (outputs.length > 0) {
-            buf.append(" = ");
-        }
-
-        if (inputs.length + alives.length != 1) {
-            buf.append("(");
-        }
-        sep = "";
-        for (CiValue input : inputs) {
-            buf.append(sep).append(input);
-            sep = ", ";
-        }
-        for (CiValue input : alives) {
-            buf.append(sep).append(input).append(" ~");
-            sep = ", ";
-        }
-        if (inputs.length + alives.length != 1) {
-            buf.append(")");
-        }
-
-        if (temps.length > 0) {
-            buf.append(" [");
-        }
-        sep = "";
-        for (CiValue temp : temps) {
-            buf.append(sep).append(temp);
-            sep = ", ";
-        }
-        if (temps.length > 0) {
-            buf.append("]");
-        }
-        return buf.toString();
-    }
-
-    protected void appendDebugInfo(StringBuilder buf) {
-        if (info != null) {
-            buf.append(" [bci:");
-            String sep = "";
-            for (CiFrame cur = info.topFrame; cur != null; cur = cur.caller()) {
-                buf.append(sep).append(cur.bci);
-                sep = ",";
-            }
-            buf.append("]");
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder buf = new StringBuilder(name()).append(' ').append(operationString());
-        appendDebugInfo(buf);
-        return buf.toString();
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.lir;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.nodes.*;
-import com.oracle.max.graal.nodes.PhiNode.*;
-
-public class LIRPhiMapping {
-    private final Block block;
-
-    private CiValue[][] inputs;
-    private CiValue[] results;
-
-    public LIRPhiMapping(Block block, LIRGenerator gen) {
-        this.block = block;
-
-        assert block.getBeginNode() instanceof MergeNode : "phi functions are only present at control flow merges";
-        MergeNode mergeNode = (MergeNode) block.getBeginNode();
-        List<PhiNode> phis = mergeNode.phis().snapshot();
-
-        for (int i = 0; i < phis.size(); i++) {
-            PhiNode phi = phis.get(i);
-            if (phi.type() == PhiType.Value) {
-                gen.setResult(phi, gen.newVariable(phi.kind()));
-            }
-        }
-    }
-
-    public void fillInputs(LIRGenerator gen) {
-        assert block.getBeginNode() instanceof MergeNode : "phi functions are only present at control flow merges";
-        MergeNode mergeNode = (MergeNode) block.getBeginNode();
-        List<PhiNode> phis = mergeNode.phis().snapshot();
-
-        int numPhis = 0;
-        for (int i = 0; i < phis.size(); i++) {
-            if (phis.get(i).type() == PhiType.Value) {
-                numPhis++;
-            }
-        }
-        int numPreds = block.numberOfPreds();
-
-        results = new CiValue[numPhis];
-        inputs = new CiValue[numPreds][numPhis];
-
-        int phiIdx = 0;
-        for (int i = 0; i < phis.size(); i++) {
-            PhiNode phi = phis.get(i);
-            if (phi.type() == PhiType.Value) {
-                results[phiIdx] = gen.operand(phi);
-                for (int j = 0; j < numPreds; j++) {
-                    assert j == mergeNode.phiPredecessorIndex((FixedNode) block.predAt(j).getEndNode()) : "block predecessors and node predecessors must have same order";
-                    inputs[j][phiIdx] = gen.operand(phi.valueAt(j));
-                }
-                phiIdx++;
-            }
-        }
-        assert phiIdx == numPhis;
-    }
-
-    public CiValue[] results() {
-        return results;
-    }
-
-    public CiValue[] inputs(Block pred) {
-        assert pred.numberOfSux() == 1 && pred.suxAt(0) == block;
-        return inputs[block.getPredecessors().indexOf(pred)];
-    }
-
-    private static final EnumSet<OperandFlag> INPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-    private static final EnumSet<OperandFlag> OUTPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-
-    public void forEachInput(Block pred, PhiValueProcedure proc) {
-        CiValue[] predInputs = inputs(pred);
-        for (int i = 0; i < predInputs.length; i++) {
-            predInputs[i] = proc.doValue(predInputs[i], results[i]);
-        }
-    }
-
-    public void forEachOutput(ValueProcedure proc) {
-        for (int i = 0; i < results.length; i++) {
-            results[i] = proc.doValue(results[i], OperandMode.Output, OUTPUT_FLAGS);
-        }
-    }
-
-    public abstract static class PhiValueProcedure extends ValueProcedure {
-        /**
-         * Iterator method to be overwritten. This version of the iterator has both the input and output of the phi function as parameters.
-         * to keep the signature short.
-         *
-         * @param input The input value that is iterated.
-         * @param output The output value that is iterated.
-         * @return The new value to replace the input value that was passed in.
-         */
-        protected CiValue doValue(CiValue input, CiValue output) {
-            return doValue(input, OperandMode.Input, INPUT_FLAGS);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "PhiMapping for " + block + ": " + Arrays.toString(results);
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.lir;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
-import com.oracle.max.graal.compiler.util.*;
-
-public final class LIRVerifier {
-    private final LIR lir;
-    private final FrameMap frameMap;
-
-    private final boolean beforeRegisterAllocation;
-
-    private final BitSet[] blockLiveOut;
-    private final Object[] variableDefinitions;
-
-    private BitSet liveOutFor(Block block) {
-        return blockLiveOut[block.getId()];
-    }
-    private void setLiveOutFor(Block block, BitSet liveOut) {
-        blockLiveOut[block.getId()] = liveOut;
-    }
-
-    private int maxRegisterNum() {
-        return frameMap.target.arch.registers.length;
-    }
-
-    private boolean isAllocatableRegister(CiValue value) {
-        return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
-    }
-
-    public static boolean verify(final LIRInstruction op) {
-        ValueProcedure allowedProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return allowed(op, value, mode, flags); } };
-
-        op.forEachInput(allowedProc);
-        op.forEachAlive(allowedProc);
-        op.forEachState(allowedProc);
-        op.forEachTemp(allowedProc);
-        op.forEachOutput(allowedProc);
-
-        op.verify();
-        return true;
-    }
-
-    public static boolean verify(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) {
-        LIRVerifier verifier = new LIRVerifier(beforeRegisterAllocation, lir, frameMap);
-        verifier.verify();
-        return true;
-    }
-
-
-    private LIRVerifier(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) {
-        this.beforeRegisterAllocation = beforeRegisterAllocation;
-        this.lir = lir;
-        this.frameMap = frameMap;
-        this.blockLiveOut = new BitSet[lir.linearScanOrder().size()];
-        this.variableDefinitions = new Object[lir.numVariables()];
-    }
-
-    private BitSet curVariablesLive;
-    private CiValue[] curRegistersLive;
-
-    private Block curBlock;
-    private Object curInstruction;
-    private BitSet curRegistersDefined;
-
-    private void verify() {
-        PhiValueProcedure useProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
-        ValueProcedure defProc =    new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } };
-
-        curRegistersDefined = new BitSet();
-        for (Block block : lir.linearScanOrder()) {
-            curBlock = block;
-            curVariablesLive = new BitSet();
-            curRegistersLive = new CiValue[maxRegisterNum()];
-
-            if (block.getDominator() != null) {
-                curVariablesLive.or(liveOutFor(block.getDominator()));
-            }
-
-            if (block.phis != null) {
-                assert beforeRegisterAllocation;
-                curInstruction = block.phis;
-                block.phis.forEachOutput(defProc);
-            }
-
-            assert block.lir.get(0) instanceof StandardOp.LabelOp : "block must start with label";
-            if (block.numberOfSux() > 0) {
-                LIRInstruction last = block.lir.get(block.lir.size() - 1);
-                assert last instanceof StandardOp.JumpOp || last instanceof LIRXirInstruction : "block with successor must end with unconditional jump";
-            }
-
-            for (LIRInstruction op : block.lir) {
-                curInstruction = op;
-
-                op.forEachInput(useProc);
-                if (op.hasCall()) {
-                    for (CiRegister register : frameMap.registerConfig.getCallerSaveRegisters()) {
-                        curRegistersLive[register.number] = null;
-                    }
-                }
-                curRegistersDefined.clear();
-                op.forEachAlive(useProc);
-                op.forEachState(useProc);
-                op.forEachTemp(defProc);
-                op.forEachOutput(defProc);
-
-                curInstruction = null;
-            }
-
-            for (Block sux : block.getSuccessors()) {
-                if (sux.phis != null) {
-                    assert beforeRegisterAllocation;
-                    curInstruction = sux.phis;
-                    sux.phis.forEachInput(block, useProc);
-                }
-            }
-
-            setLiveOutFor(block, curVariablesLive);
-        }
-    }
-
-    private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        allowed(curInstruction, value, mode, flags);
-
-        if (isVariable(value)) {
-            assert beforeRegisterAllocation;
-
-            int variableIdx = asVariable(value).index;
-            if (!curVariablesLive.get(variableIdx)) {
-                TTY.println("block %s  instruction %s", curBlock, curInstruction);
-                TTY.println("live variables: %s", curVariablesLive);
-                if (variableDefinitions[variableIdx] != null) {
-                    TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]);
-                }
-                TTY.println("ERROR: Use of variable %s that is not defined in dominator", value);
-                throw Util.shouldNotReachHere();
-            }
-
-        } else if (isAllocatableRegister(value)) {
-            int regNum = asRegister(value).number;
-            if (mode == OperandMode.Alive) {
-                curRegistersDefined.set(regNum);
-            }
-
-            if (beforeRegisterAllocation && curRegistersLive[regNum] != value) {
-                TTY.println("block %s  instruction %s", curBlock, curInstruction);
-                TTY.println("live registers: %s", Arrays.toString(curRegistersLive));
-                TTY.println("ERROR: Use of fixed register %s that is not defined in this block", value);
-                throw Util.shouldNotReachHere();
-            }
-        }
-        return value;
-    }
-
-    private CiValue def(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        allowed(curInstruction, value, mode, flags);
-
-        if (isVariable(value)) {
-            assert beforeRegisterAllocation;
-
-            int variableIdx = asVariable(value).index;
-            if (variableDefinitions[variableIdx] != null) {
-                TTY.println("block %s  instruction %s", curBlock, curInstruction);
-                TTY.println("live variables: %s", curVariablesLive);
-                TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]);
-                TTY.println("ERROR: Variable %s defined multiple times", value);
-                throw Util.shouldNotReachHere();
-            }
-            assert curInstruction != null;
-            variableDefinitions[variableIdx] = curInstruction;
-            assert !curVariablesLive.get(variableIdx);
-            if (mode == OperandMode.Output) {
-                curVariablesLive.set(variableIdx);
-            }
-
-        } else if (isAllocatableRegister(value)) {
-            int regNum = asRegister(value).number;
-            if (curRegistersDefined.get(regNum)) {
-                TTY.println("block %s  instruction %s", curBlock, curInstruction);
-                TTY.println("ERROR: Same register defined twice in the same instruction: %s", value);
-                throw Util.shouldNotReachHere();
-            }
-            curRegistersDefined.set(regNum);
-
-            if (beforeRegisterAllocation) {
-                if (mode == OperandMode.Output) {
-                    curRegistersLive[regNum] = value;
-                } else {
-                    curRegistersLive[regNum] = null;
-                }
-            }
-        }
-        return value;
-    }
-
-    private static CiValue allowed(Object op, CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        if ((isVariable(value)  && flags.contains(OperandFlag.Register)) ||
-            (isRegister(value)  && flags.contains(OperandFlag.Register)) ||
-            (isStackSlot(value) && flags.contains(OperandFlag.Stack)) ||
-            (isConstant(value)  && flags.contains(OperandFlag.Constant) && mode != OperandMode.Output) ||
-            (isIllegal(value)   && flags.contains(OperandFlag.Illegal))) {
-            return value;
-        }
-        TTY.println("instruction %s", op);
-        TTY.println("mode: %s  flags: %s", mode, flags);
-        TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value);
-        throw Util.shouldNotReachHere();
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.lir;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.xir.*;
-import com.oracle.max.graal.compiler.util.*;
-
-public abstract class LIRXirInstruction extends LIRInstruction {
-
-    public final CiValue[] originalOperands;
-    public final int outputOperandIndex;
-    public final int[] inputOperandIndices;
-    public final int[] tempOperandIndices;
-    public final XirSnippet snippet;
-    public final LIRDebugInfo infoAfter;
-    public final LabelRef trueSuccessor;
-    public final LabelRef falseSuccessor;
-
-    public LIRXirInstruction(Object opcode,
-                             XirSnippet snippet,
-                             CiValue[] originalOperands,
-                             CiValue outputOperand,
-                             CiValue[] inputs, CiValue[] temps,
-                             int[] inputOperandIndices, int[] tempOperandIndices,
-                             int outputOperandIndex,
-                             LIRDebugInfo info,
-                             LIRDebugInfo infoAfter,
-                             LabelRef trueSuccessor,
-                             LabelRef falseSuccessor) {
-        // Note that we register the XIR input operands as Alive, because the XIR specification allows that input operands
-        // are used at any time, even when the temp operands and the actual output operands have already be assigned.
-        super(opcode, isLegal(outputOperand) ? new CiValue[] {outputOperand} : LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, inputs, temps);
-        this.infoAfter = infoAfter;
-        this.snippet = snippet;
-        this.inputOperandIndices = inputOperandIndices;
-        this.tempOperandIndices = tempOperandIndices;
-        this.outputOperandIndex = outputOperandIndex;
-        this.originalOperands = originalOperands;
-        this.falseSuccessor = falseSuccessor;
-        this.trueSuccessor = trueSuccessor;
-        assert isLegal(outputOperand) || outputOperandIndex == -1;
-    }
-
-    @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        if (mode == OperandMode.Alive || mode == OperandMode.Temp) {
-            return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Illegal);
-        } else if (mode == OperandMode.Output && index == 0) {
-            return EnumSet.of(OperandFlag.Register);
-        }
-        throw Util.shouldNotReachHere();
-    }
-
-    public CiValue[] getOperands() {
-        for (int i = 0; i < inputOperandIndices.length; i++) {
-            originalOperands[inputOperandIndices[i]] = alive(i);
-        }
-        for (int i = 0; i < tempOperandIndices.length; i++) {
-            originalOperands[tempOperandIndices[i]] = temp(i);
-        }
-        if (outputOperandIndex != -1) {
-            originalOperands[outputOperandIndex] = output(0);
-        }
-        return originalOperands;
-    }
-
-    @Override
-    public String name() {
-        return "XIR: " + snippet.template;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LabelRef.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.lir;
-
-import com.oracle.max.asm.*;
-import com.oracle.max.graal.compiler.cfg.*;
-
-/**
- * LIR instructions such as JUMP and BRANCH need to reference their target {@link Block}. However,
- * direct references are not possible since the control flow graph (and therefore successors lists) can
- * be changed by optimizations - and fixing the instructions is error prone.
- * Therefore, we only reference of block B from block A only via the tuple (A, successor-index-of-B), i.e.,
- * indirectly by storing the index into the successor list of A.
- * Note that therefore it is not allowed to reorder the successor list!
- *
- * Labels of out-of-line stubs can be referenced directly, therefore it is also possible to construct a
- * LabelRef for a Label directly via {@link #forLabel}.
- */
-public abstract class LabelRef {
-
-    public abstract Label label();
-
-    /**
-     * Returns a new reference to a statically defined label.
-     * @param label The label that is always returned.
-     * @return The newly created label reference.
-     */
-    public static LabelRef forLabel(final Label label) {
-       return new LabelRef() {
-           @Override
-           public Label label() {
-               return label;
-           }
-
-           @Override
-           public String toString() {
-               return label.toString();
-           }
-       };
-    }
-
-    /**
-     * Returns a new reference to a successor of the given block.
-     * This allows to reference the given successor even when the successor list
-     * is modified between the creation of the reference and the call to {@link #getLabel}.
-     * @param block The base block that contains the successor list.
-     * @param suxIndex The index of the successor.
-     * @return The newly created label reference.
-     */
-    public static LabelRef forSuccessor(final Block block, final int suxIndex) {
-        return new LabelRef() {
-            @Override
-            public Label label() {
-                return ((StandardOp.LabelOp) block.suxAt(suxIndex).lir.get(0)).getLabel();
-            }
-
-            @Override
-            public String toString() {
-                return suxIndex < block.numberOfSux() ? block.suxAt(suxIndex).toString() : "?" + block + ":" + suxIndex + "?";
-            }
-        };
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.lir;
-
-import java.util.*;
-
-import com.oracle.max.asm.*;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.util.*;
-
-/**
- * A collection of machine-independent LIR operations, as well as interfaces to be implemented for specific kinds or LIR
- * operations.
- */
-public class StandardOp {
-
-    /**
-     * Marker interface for a LIR operation that defines the position of a label.
-     * The first operation of every block must implement this interface.
-     */
-    public interface LabelOp {
-        Label getLabel();
-    }
-
-    /**
-     * Marker interface for a LIR operation that is an unconditional jump to {@link #destination()}.
-     * When the LIR is constructed, the last operation of every block must implement this interface. After
-     * register allocation, unnecessary jumps can be deleted.
-     *
-     * TODO Currently, a block can also end with an XIR operation.
-     */
-    public interface JumpOp {
-        LabelRef destination();
-    }
-
-    /**
-     * Marker interface for a LIR operation that is a conditional jump to {@link #destination()}.
-     * Conditional jumps may be negated or optimized away after register allocation.
-     */
-    public interface BranchOp {
-        LabelRef destination();
-        void negate(LabelRef newDestination);
-    }
-
-    /**
-     * Marker interface for a LIR operation that moves a value from {@link #getInput()} to {@link #getResult()}.
-     */
-    public interface MoveOp {
-        CiValue getInput();
-        CiValue getResult();
-    }
-
-    /**
-     * Marker interface for a LIR operation that calls a method, i.e., destroys all caller-saved registers.
-     */
-    public interface CallOp {
-    }
-
-
-    /**
-     * Meta-operation that defines the incoming method parameters. In the LIR, every register and variable must be
-     * defined before it is used. This operation is the definition point of method parameters, but is otherwise a no-op.
-     * In particular, it is not the actual method prologue.
-     */
-    public static final class ParametersOp extends LIRInstruction {
-        public ParametersOp(CiValue[] params) {
-            super("PARAMS", params, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm) {
-            // No code to emit.
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Output) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/Variable.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.lir;
-
-import com.oracle.max.cri.ci.*;
-
-/**
- * Represents a value that is yet to be bound to a machine location (such as
- * a {@link CiRegisterValue} or {@link CiStackSlot}) by a register allocator.
- */
-public final class Variable extends CiValue {
-    private static final long serialVersionUID = 4507578431686109809L;
-
-    /**
-     * The identifier of the variable. This is a non-zero index in a contiguous 0-based name space.
-     */
-    public final int index;
-
-    /**
-     * The type of register that this variable needs to get assigned.
-     */
-    public final CiRegister.RegisterFlag flag;
-
-    /**
-     * Creates a new variable.
-     * @param kind
-     * @param index
-     */
-    public Variable(CiKind kind, int index, CiRegister.RegisterFlag flag) {
-        super(kind);
-        assert kind == kind.stackKind() : "Variables can be only created for stack kinds";
-        assert index >= 0;
-        this.index = index;
-        this.flag = flag;
-    }
-
-    @Override
-    public int hashCode() {
-        return (index << 4) | kind.ordinal();
-    }
-
-    @Override
-    public String toString() {
-        return "v" + index + kindSuffix();
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/CompilationEvent.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.observer;
-
-import java.util.*;
-
-/**
- * An event that occurred during compilation. Instances of this class provide information about the event and the state
- * of the compilation when the event was raised. Depending on the state of the compiler and the compilation phase,
- * different types of objects are provided in the {@link #debugObjects}. The observer should filter events that it is
- * interested in by checking if an object of a specific type is provided by the event.
- */
-public class CompilationEvent {
-
-    /**
-     * Marker object for the {@link #debugObject} array: When this object is present, the event is the result of a compilation error.
-     */
-    public static final Object ERROR = new Object() {};
-
-    public final String label;
-    private List<Object> debugObjects;
-
-    protected CompilationEvent(String label, ArrayList<Object> debugObjects) {
-        this.label = label;
-        this.debugObjects = debugObjects;
-    }
-
-    @SuppressWarnings("unchecked")
-    public <T> T debugObject(Class<T> type) {
-        for (ListIterator<Object> iter = debugObjects.listIterator(debugObjects.size()); iter.hasPrevious();) {
-            Object o = iter.previous();
-            if (type.isInstance(o)) {
-                return (T) o;
-            }
-        }
-        return null;
-    }
-
-    public boolean hasDebugObject(Object search) {
-        for (ListIterator<Object> iter = debugObjects.listIterator(debugObjects.size()); iter.hasPrevious();) {
-            Object o = iter.previous();
-            if (o == search) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/CompilationObserver.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.observer;
-
-
-/**
- * Interface for classes that observe events of an {@link ObservableCompiler}.
- */
-public interface CompilationObserver {
-
-    /**
-     * Called when compilation of a method has started. This is always the first event raised for a particular
-     * method compilation.
-     *
-     * @param event Information associated with the event and current state of the compilation.
-     */
-    void compilationStarted(CompilationEvent event);
-
-    /**
-     * Called when an event has occurred, for example that a particular phase in the compilation has been entered.
-     *
-     * @param event Information associated with the event and current state of the compilation.
-     */
-    void compilationEvent(CompilationEvent event);
-
-    /**
-     * Called when compilation of a method has completed (successfully or not). This is always the last event raised for
-     * a particular method compilation.
-     *
-     * @param event Information associated with the event and current state of the compilation.
-     */
-    void compilationFinished(CompilationEvent event);
-
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/ObservableContext.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.observer;
-
-import java.util.*;
-
-/**
- * Base class for compilers that notify subscribed {@link CompilationObserver CompilationObservers} of
- * {@link CompilationEvent CompilationEvents} that occur during their compilations.
- */
-public class ObservableContext {
-
-    private List<CompilationObserver> observers;
-
-    private ThreadLocal<StringBuilder> scopeName = new ThreadLocal<StringBuilder>() {
-        @Override
-        protected StringBuilder initialValue() {
-            return new StringBuilder();
-        }
-    };
-
-    private ThreadLocal<ArrayList<Object>> debugObjects = new ThreadLocal<ArrayList<Object>>() {
-        @Override
-        protected ArrayList<Object> initialValue() {
-            return new ArrayList<>();
-        }
-    };
-
-    /**
-     * @return {@code true} if one or more observers are subscribed to receive notifications from this compiler,
-     *         {@code false} otherwise.
-     */
-    public boolean isObserved() {
-        return observers != null;
-    }
-
-    /**
-     * Add the specified observer to receive events from this compiler.
-     *
-     * @param observer The observer to add.
-     */
-    public void addCompilationObserver(CompilationObserver observer) {
-        assert observer != null;
-
-        if (observers == null) {
-            observers = new LinkedList<>();
-        }
-        observers.add(observer);
-    }
-
-    public void fireCompilationStarted(Object... additionalDebugObjects) {
-        if (isObserved()) {
-            addDebugObjects(null, additionalDebugObjects);
-            CompilationEvent event = new CompilationEvent("started", debugObjects.get());
-            for (CompilationObserver observer : observers) {
-                observer.compilationStarted(event);
-            }
-            removeDebugObjects(null, additionalDebugObjects);
-        }
-    }
-
-    public void fireCompilationEvent(String label, Object... additionalDebugObjects) {
-        if (isObserved()) {
-            addDebugObjects(null, additionalDebugObjects);
-            CompilationEvent event = new CompilationEvent(label, debugObjects.get());
-            for (CompilationObserver observer : observers) {
-                observer.compilationEvent(event);
-            }
-            removeDebugObjects(null, additionalDebugObjects);
-        }
-    }
-
-    public void fireCompilationFinished(Object... additionalDebugObjects) {
-        if (isObserved()) {
-            addDebugObjects(null, additionalDebugObjects);
-            CompilationEvent event = new CompilationEvent("finished", debugObjects.get());
-            for (CompilationObserver observer : observers) {
-                observer.compilationFinished(event);
-            }
-            removeDebugObjects(null, additionalDebugObjects);
-        }
-    }
-
-    /**
-     * Remove the specified observer so that it no longer receives events from this compiler.
-     *
-     * @param observer The observer to remove.
-     */
-    public void removeCompilationObserver(CompilationObserver observer) {
-        if (observers != null) {
-            observers.remove(observer);
-            if (observers.size() == 0) {
-                observers = null;
-            }
-        }
-    }
-
-    public void clear() {
-        if (observers != null) {
-            observers = null;
-        }
-    }
-
-    public void addDebugObjects(String name, Object[] additionalDebugObjects) {
-        if (name != null) {
-            if (scopeName.get().length() > 0) {
-                scopeName.get().append('.');
-            }
-            scopeName.get().append(name);
-        }
-        for (Object obj : additionalDebugObjects) {
-            debugObjects.get().add(obj);
-        }
-    }
-
-    public void removeDebugObjects(String name, Object[] additionalDebugObjects) {
-        if (name != null) {
-            scopeName.get().setLength(Math.max(0, scopeName.get().length() - name.length()));
-        }
-        for (int i = 0; i < additionalDebugObjects.length; i++) {
-            debugObjects.get().remove(debugObjects.get().size() - 1);
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/package-info.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * Classes and interfaces for observing compilations.
- */
-package com.oracle.max.graal.compiler.observer;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Wed Feb 08 21:15:00 2012 -0800
@@ -87,7 +87,7 @@
                             graph.removeFloating((FloatingNode) node);
                         } else {
                             // case 2
-                            assert canonical instanceof FloatingNode || (canonical instanceof FixedNode && canonical.predecessor() != null) : node + " -> " + canonical +
+                            assert !(canonical instanceof FixedNode) || canonical.predecessor() != null : node + " -> " + canonical +
                                             " : replacement should be floating or fixed and connected";
                             graph.replaceFloating((FloatingNode) node, canonical);
                         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java	Wed Feb 08 21:15:00 2012 -0800
@@ -25,9 +25,9 @@
 import java.util.*;
 
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.PhiNode.PhiType;
 import com.oracle.max.graal.nodes.extended.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Wed Feb 08 21:15:00 2012 -0800
@@ -197,7 +197,7 @@
         } else if (GraalOptions.InliningPolicy == 3) {
             return new GreedySizeBasedInliningPolicy();
         } else {
-            Util.shouldNotReachHere();
+            GraalInternalError.shouldNotReachHere();
             return null;
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Wed Feb 08 21:15:00 2012 -0800
@@ -23,9 +23,9 @@
 package com.oracle.max.graal.compiler.phases;
 
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.cri.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.spi.*;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/BlockClosure.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/BlockClosure.java	Wed Feb 08 21:15:00 2012 -0800
@@ -22,7 +22,7 @@
  */
 package com.oracle.max.graal.compiler.schedule;
 
-import com.oracle.max.graal.compiler.cfg.*;
+import com.oracle.max.graal.lir.cfg.*;
 
 /**
  * The {@code BlockClosure} interface represents a closure for iterating over blocks.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/SchedulePhase.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/SchedulePhase.java	Wed Feb 08 21:15:00 2012 -0800
@@ -27,10 +27,10 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.phases.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.graph.Node.Verbosity;
+import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.extended.*;
 import com.oracle.max.graal.nodes.virtual.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/Backend.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/Backend.java	Wed Feb 08 21:15:00 2012 -0800
@@ -29,8 +29,8 @@
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.cri.xir.*;
 import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
 
 /**
  * The {@code Backend} class represents a compiler backend for Graal.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Arithmetic.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,559 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.target.amd64;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.asm.*;
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.util.*;
-
-public enum AMD64Arithmetic {
-    IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
-    LADD, LSUB, LMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
-    FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR,
-    DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR,
-    INEG, LNEG,
-    I2L, L2I, I2B, I2C, I2S,
-    F2D, D2F,
-    I2F, I2D, F2I, D2I,
-    L2F, L2D, F2L, D2L,
-    MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L;
-
-
-    public static class Op1Reg extends AMD64LIRInstruction {
-        public Op1Reg(AMD64Arithmetic opcode, CiValue result, CiValue x) {
-            super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            CiValue result = output(0);
-            CiValue x = input(0);
-
-            emit(tasm, masm, (AMD64Arithmetic) code, result, x, null);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-    public static class Op1Stack extends AMD64LIRInstruction {
-        public Op1Stack(AMD64Arithmetic opcode, CiValue result, CiValue x) {
-            super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            CiValue result = output(0);
-            CiValue x = input(0);
-
-            AMD64Move.move(tasm, masm, result, x);
-            emit(tasm, masm, (AMD64Arithmetic) code, result);
-        }
-
-        @Override
-        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-    public static class Op2Stack extends AMD64LIRInstruction {
-        public Op2Stack(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) {
-            super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            CiValue result = output(0);
-            CiValue x = input(0);
-            CiValue y = alive(0);
-
-            AMD64Move.move(tasm, masm, result, x);
-            emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw Util.shouldNotReachHere();
-        }
-
-        @Override
-        public void verify() {
-            CiValue result = output(0);
-            CiValue x = input(0);
-            CiValue y = alive(0);
-
-            super.verify();
-            assert differentRegisters(result, y) || sameRegister(x, y);
-            verifyKind((AMD64Arithmetic) code, result, x, y);
-        }
-    }
-
-    public static class Op2Reg extends AMD64LIRInstruction {
-        public Op2Reg(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) {
-            super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            CiValue result = output(0);
-            CiValue x = input(0);
-            CiValue y = alive(0);
-
-            AMD64Move.move(tasm, masm, result, x);
-            emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw Util.shouldNotReachHere();
-        }
-
-        @Override
-        public void verify() {
-            CiValue result = output(0);
-            CiValue x = input(0);
-            CiValue y = alive(0);
-
-            super.verify();
-            assert differentRegisters(result, y) || sameRegister(x, y);
-            verifyKind((AMD64Arithmetic) code, result, x, y);
-        }
-    }
-
-    public static class Op2RegCommutative extends AMD64LIRInstruction {
-        public Op2RegCommutative(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) {
-            super(opcode, new CiValue[] {result}, null, new CiValue[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            CiValue result = output(0);
-            CiValue x = input(0);
-            CiValue y = input(1);
-
-            if (sameRegister(result, y)) {
-                emit(tasm, masm, (AMD64Arithmetic) code, result, x, null);
-            } else {
-                AMD64Move.move(tasm, masm, result, x);
-                emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
-            }
-        }
-
-        @Override
-        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Input && index == 1) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw Util.shouldNotReachHere();
-        }
-
-        @Override
-        protected void verify() {
-            CiValue result = output(0);
-            CiValue x = input(0);
-            CiValue y = input(1);
-
-            super.verify();
-            verifyKind((AMD64Arithmetic) code, result, x, y);
-        }
-    }
-
-    public static class ShiftOp extends AMD64LIRInstruction {
-        public ShiftOp(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) {
-            super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            CiValue result = output(0);
-            CiValue x = input(0);
-            CiValue y = alive(0);
-
-            AMD64Move.move(tasm, masm, result, x);
-            emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
-        }
-
-        @Override
-        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw Util.shouldNotReachHere();
-        }
-
-        @Override
-        public void verify() {
-            CiValue result = output(0);
-            CiValue x = input(0);
-            CiValue y = alive(0);
-
-            super.verify();
-            assert isConstant(y) || asRegister(y) == AMD64.rcx;
-            assert differentRegisters(result, y) || sameRegister(x, y);
-            verifyKind((AMD64Arithmetic) code, result, x, x);
-            assert y.kind.stackKind() == CiKind.Int;
-        }
-    }
-
-    public static class DivOp extends AMD64LIRInstruction {
-        public DivOp(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y, LIRDebugInfo info) {
-            super(opcode, new CiValue[] {result}, info, new CiValue[] {x}, new CiValue[] {y}, new CiValue[] {asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind)});
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            CiValue result = output(0);
-            CiValue y = alive(0);
-
-            emit(tasm, masm, (AMD64Arithmetic) code, result, y, info);
-        }
-
-        @Override
-        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Temp && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw Util.shouldNotReachHere();
-        }
-
-        @Override
-        protected void verify() {
-            CiValue result = output(0);
-            CiValue x = input(0);
-            CiValue y = alive(0);
-
-            super.verify();
-            // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx
-            assert asRegister(x) == AMD64.rax;
-            assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue());
-            assert (name().endsWith("DIV") && asRegister(result) == AMD64.rax) || (name().endsWith("REM") && asRegister(result) == AMD64.rdx);
-            verifyKind((AMD64Arithmetic) code, result, x, y);
-        }
-    }
-
-
-    @SuppressWarnings("unused")
-    protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, CiValue result) {
-        switch (opcode) {
-            case INEG: masm.negl(asIntReg(result)); break;
-            case LNEG: masm.negq(asLongReg(result)); break;
-            case L2I:  masm.andl(asIntReg(result), 0xFFFFFFFF); break;
-            case I2B:  masm.signExtendByte(asIntReg(result)); break;
-            case I2C:  masm.andl(asIntReg(result), 0xFFFF); break;
-            case I2S:  masm.signExtendShort(asIntReg(result)); break;
-            default:   throw Util.shouldNotReachHere();
-        }
-    }
-
-    protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, CiValue dst, CiValue src, LIRDebugInfo info) {
-        int exceptionOffset = -1;
-        if (isRegister(src)) {
-            switch (opcode) {
-                case IADD: masm.addl(asIntReg(dst),  asIntReg(src)); break;
-                case ISUB: masm.subl(asIntReg(dst),  asIntReg(src)); break;
-                case IAND: masm.andl(asIntReg(dst),  asIntReg(src)); break;
-                case IMUL: masm.imull(asIntReg(dst), asIntReg(src)); break;
-                case IOR:  masm.orl(asIntReg(dst),   asIntReg(src)); break;
-                case IXOR: masm.xorl(asIntReg(dst),  asIntReg(src)); break;
-                case ISHL: masm.shll(asIntReg(dst)); break;
-                case ISHR: masm.sarl(asIntReg(dst)); break;
-                case IUSHR:masm.shrl(asIntReg(dst)); break;
-
-                case LADD: masm.addq(asLongReg(dst),  asLongReg(src)); break;
-                case LSUB: masm.subq(asLongReg(dst),  asLongReg(src)); break;
-                case LMUL: masm.imulq(asLongReg(dst), asLongReg(src)); break;
-                case LAND: masm.andq(asLongReg(dst),  asLongReg(src)); break;
-                case LOR:  masm.orq(asLongReg(dst),   asLongReg(src)); break;
-                case LXOR: masm.xorq(asLongReg(dst),  asLongReg(src)); break;
-                case LSHL: masm.shlq(asLongReg(dst)); break;
-                case LSHR: masm.sarq(asLongReg(dst)); break;
-                case LUSHR:masm.shrq(asLongReg(dst)); break;
-
-                case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); break;
-                case FSUB: masm.subss(asFloatReg(dst), asFloatReg(src)); break;
-                case FMUL: masm.mulss(asFloatReg(dst), asFloatReg(src)); break;
-                case FDIV: masm.divss(asFloatReg(dst), asFloatReg(src)); break;
-                case FAND: masm.andps(asFloatReg(dst), asFloatReg(src)); break;
-                case FOR:  masm.orps(asFloatReg(dst),  asFloatReg(src)); break;
-                case FXOR: masm.xorps(asFloatReg(dst), asFloatReg(src)); break;
-
-                case DADD: masm.addsd(asDoubleReg(dst), asDoubleReg(src)); break;
-                case DSUB: masm.subsd(asDoubleReg(dst), asDoubleReg(src)); break;
-                case DMUL: masm.mulsd(asDoubleReg(dst), asDoubleReg(src)); break;
-                case DDIV: masm.divsd(asDoubleReg(dst), asDoubleReg(src)); break;
-                case DAND: masm.andpd(asDoubleReg(dst), asDoubleReg(src)); break;
-                case DOR:  masm.orpd(asDoubleReg(dst),  asDoubleReg(src)); break;
-                case DXOR: masm.xorpd(asDoubleReg(dst), asDoubleReg(src)); break;
-
-                case I2L: masm.movslq(asLongReg(dst), asIntReg(src)); break;
-                case F2D: masm.cvtss2sd(asDoubleReg(dst), asFloatReg(src)); break;
-                case D2F: masm.cvtsd2ss(asFloatReg(dst), asDoubleReg(src)); break;
-                case I2F: masm.cvtsi2ssl(asFloatReg(dst), asIntReg(src)); break;
-                case I2D: masm.cvtsi2sdl(asDoubleReg(dst), asIntReg(src)); break;
-                case L2F: masm.cvtsi2ssq(asFloatReg(dst), asLongReg(src)); break;
-                case L2D: masm.cvtsi2sdq(asDoubleReg(dst), asLongReg(src)); break;
-                case F2I:
-                    masm.cvttss2sil(asIntReg(dst), asFloatReg(src));
-                    emitConvertFixup(tasm, masm, dst, src);
-                    break;
-                case D2I:
-                    masm.cvttsd2sil(asIntReg(dst), asDoubleReg(src));
-                    emitConvertFixup(tasm, masm, dst, src);
-                    break;
-                case F2L:
-                    masm.cvttss2siq(asLongReg(dst), asFloatReg(src));
-                    emitConvertFixup(tasm, masm, dst, src);
-                    break;
-                case D2L:
-                    masm.cvttsd2siq(asLongReg(dst), asDoubleReg(src));
-                    emitConvertFixup(tasm, masm, dst, src);
-                    break;
-                case MOV_I2F: masm.movdl(asFloatReg(dst), asIntReg(src)); break;
-                case MOV_L2D: masm.movdq(asDoubleReg(dst), asLongReg(src)); break;
-                case MOV_F2I: masm.movdl(asIntReg(dst), asFloatReg(src)); break;
-                case MOV_D2L: masm.movdq(asLongReg(dst), asDoubleReg(src)); break;
-
-                case IDIV:
-                case IREM:
-                    masm.cdql();
-                    exceptionOffset = masm.codeBuffer.position();
-                    masm.idivl(asRegister(src));
-                    break;
-
-                case LDIV:
-                case LREM:
-                    Label continuation = new Label();
-                    if (opcode == LDIV) {
-                        // check for special case of Long.MIN_VALUE / -1
-                        Label normalCase = new Label();
-                        masm.movq(AMD64.rdx, java.lang.Long.MIN_VALUE);
-                        masm.cmpq(AMD64.rax, AMD64.rdx);
-                        masm.jcc(ConditionFlag.notEqual, normalCase);
-                        masm.cmpl(asRegister(src), -1);
-                        masm.jcc(ConditionFlag.equal, continuation);
-                        masm.bind(normalCase);
-                    }
-
-                    masm.cdqq();
-                    exceptionOffset = masm.codeBuffer.position();
-                    masm.idivq(asRegister(src));
-                    masm.bind(continuation);
-                    break;
-
-                case IUDIV:
-                case IUREM:
-                    // Must zero the high 64-bit word (in RDX) of the dividend
-                    masm.xorq(AMD64.rdx, AMD64.rdx);
-                    exceptionOffset = masm.codeBuffer.position();
-                    masm.divl(asRegister(src));
-                    break;
-
-                case LUDIV:
-                case LUREM:
-                    // Must zero the high 64-bit word (in RDX) of the dividend
-                    masm.xorq(AMD64.rdx, AMD64.rdx);
-                    exceptionOffset = masm.codeBuffer.position();
-                    masm.divq(asRegister(src));
-                    break;
-                default:
-                    throw Util.shouldNotReachHere();
-            }
-        } else if (isConstant(src)) {
-            switch (opcode) {
-                case IADD: masm.incrementl(asIntReg(dst), tasm.asIntConst(src)); break;
-                case ISUB: masm.decrementl(asIntReg(dst), tasm.asIntConst(src)); break;
-                case IMUL: masm.imull(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break;
-                case IAND: masm.andl(asIntReg(dst), tasm.asIntConst(src)); break;
-                case IOR:  masm.orl(asIntReg(dst),  tasm.asIntConst(src)); break;
-                case IXOR: masm.xorl(asIntReg(dst), tasm.asIntConst(src)); break;
-                case ISHL: masm.shll(asIntReg(dst), tasm.asIntConst(src) & 31); break;
-                case ISHR: masm.sarl(asIntReg(dst), tasm.asIntConst(src) & 31); break;
-                case IUSHR:masm.shrl(asIntReg(dst), tasm.asIntConst(src) & 31); break;
-
-                case LADD: masm.addq(asLongReg(dst), tasm.asIntConst(src)); break;
-                case LSUB: masm.subq(asLongReg(dst), tasm.asIntConst(src)); break;
-                case LMUL: masm.imulq(asLongReg(dst), asLongReg(dst), tasm.asIntConst(src)); break;
-                case LAND: masm.andq(asLongReg(dst), tasm.asIntConst(src)); break;
-                case LOR:  masm.orq(asLongReg(dst),  tasm.asIntConst(src)); break;
-                case LXOR: masm.xorq(asLongReg(dst), tasm.asIntConst(src)); break;
-                case LSHL: masm.shlq(asLongReg(dst), tasm.asIntConst(src) & 63); break;
-                case LSHR: masm.sarq(asLongReg(dst), tasm.asIntConst(src) & 63); break;
-                case LUSHR:masm.shrq(asLongReg(dst), tasm.asIntConst(src) & 63); break;
-
-                case FADD: masm.addss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
-                case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
-                case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
-                case FAND: masm.andps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break;
-                case FOR:  masm.orps(asFloatReg(dst),  tasm.asFloatConstRef(src, 16)); break;
-                case FXOR: masm.xorps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break;
-                case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
-
-                case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
-                case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
-                case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
-                case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
-                case DAND: masm.andpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break;
-                case DOR:  masm.orpd(asDoubleReg(dst),  tasm.asDoubleConstRef(src, 16)); break;
-                case DXOR: masm.xorpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break;
-                default:   throw Util.shouldNotReachHere();
-            }
-        } else {
-            switch (opcode) {
-                case IADD: masm.addl(asIntReg(dst), tasm.asIntAddr(src)); break;
-                case ISUB: masm.subl(asIntReg(dst), tasm.asIntAddr(src)); break;
-                case IAND: masm.andl(asIntReg(dst), tasm.asIntAddr(src)); break;
-                case IOR:  masm.orl(asIntReg(dst),  tasm.asIntAddr(src)); break;
-                case IXOR: masm.xorl(asIntReg(dst), tasm.asIntAddr(src)); break;
-
-                case LADD: masm.addq(asLongReg(dst), tasm.asLongAddr(src)); break;
-                case LSUB: masm.subq(asLongReg(dst), tasm.asLongAddr(src)); break;
-                case LAND: masm.andq(asLongReg(dst), tasm.asLongAddr(src)); break;
-                case LOR:  masm.orq(asLongReg(dst),  tasm.asLongAddr(src)); break;
-                case LXOR: masm.xorq(asLongReg(dst), tasm.asLongAddr(src)); break;
-
-                case FADD: masm.addss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
-                case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
-                case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
-                case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
-
-                case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
-                case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
-                case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
-                case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
-                default:   throw Util.shouldNotReachHere();
-            }
-        }
-
-        if (info != null) {
-            assert exceptionOffset != -1;
-            tasm.recordImplicitException(exceptionOffset, info);
-        }
-    }
-
-    private static void emitConvertFixup(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x) {
-        ConvertSlowPath slowPath = new ConvertSlowPath(result, x);
-        tasm.slowPaths.add(slowPath);
-        switch (result.kind) {
-            case Int:  masm.cmpl(asIntReg(result),  Integer.MIN_VALUE); break;
-            case Long: masm.cmpq(asLongReg(result), tasm.asLongConstRef(CiConstant.forLong(java.lang.Long.MIN_VALUE))); break;
-            default:   throw Util.shouldNotReachHere();
-        }
-        masm.jcc(ConditionFlag.equal, slowPath.start);
-        masm.bind(slowPath.continuation);
-    }
-
-    private static class ConvertSlowPath extends AMD64SlowPath {
-        public final Label start = new Label();
-        public final Label continuation = new Label();
-        private final CiValue result;
-        private final CiValue x;
-
-        public ConvertSlowPath(CiValue result, CiValue x) {
-            this.result = result;
-            this.x = x;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            masm.bind(start);
-            switch (x.kind) {
-                case Float:  masm.ucomiss(asFloatReg(x),  tasm.asFloatConstRef(CiConstant.FLOAT_0)); break;
-                case Double: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(CiConstant.DOUBLE_0)); break;
-                default:     throw Util.shouldNotReachHere();
-            }
-            Label nan = new Label();
-            masm.jcc(ConditionFlag.parity, nan);
-            masm.jcc(ConditionFlag.below, continuation);
-
-            // input is > 0 -> return maxInt
-            // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff
-            switch (result.kind) {
-                case Int:  masm.decrementl(asIntReg(result),  1); break;
-                case Long: masm.decrementq(asLongReg(result), 1); break;
-                default:   throw Util.shouldNotReachHere();
-            }
-            masm.jmp(continuation);
-
-            // input is NaN -> return 0
-            masm.bind(nan);
-            masm.xorptr(asRegister(result), asRegister(result));
-            masm.jmp(continuation);
-        }
-    }
-
-
-    private static void verifyKind(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) {
-        assert (opcode.name().startsWith("I") && result.kind == CiKind.Int && x.kind.stackKind() == CiKind.Int && y.kind.stackKind() == CiKind.Int)
-            || (opcode.name().startsWith("L") && result.kind == CiKind.Long && x.kind == CiKind.Long && y.kind == CiKind.Long)
-            || (opcode.name().startsWith("F") && result.kind == CiKind.Float && x.kind == CiKind.Float && y.kind == CiKind.Float)
-            || (opcode.name().startsWith("D") && result.kind == CiKind.Double && x.kind == CiKind.Double && y.kind == CiKind.Double);
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Backend.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Backend.java	Wed Feb 08 21:15:00 2012 -0800
@@ -28,9 +28,9 @@
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.cri.xir.*;
 import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.target.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
 
 /**
  * The {@code X86Backend} class represents the backend for the AMD64 architecture.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Call.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.target.amd64;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ci.CiTargetMethod.Mark;
-import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.util.*;
-
-public class AMD64Call {
-
-    public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
-        private final Object targetMethod;
-        private final Map<XirMark, Mark> marks;
-
-        public DirectCallOp(Object targetMethod, CiValue result, CiValue[] parameters, LIRDebugInfo info, Map<XirMark, Mark> marks) {
-            super("CALL_DIRECT", new CiValue[] {result}, info, parameters, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-            this.targetMethod = targetMethod;
-            this.marks = marks;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            callAlignment(tasm, masm);
-            if (marks != null) {
-                marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0]));
-            }
-            directCall(tasm, masm, targetMethod, info);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            } else if (mode == OperandMode.Output) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-    public static class IndirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
-        private final Object targetMethod;
-        private final Map<XirMark, Mark> marks;
-
-        private static CiValue[] concat(CiValue[] parameters, CiValue targetAddress) {
-            CiValue[] result = Arrays.copyOf(parameters, parameters.length + 1);
-            result[result.length - 1] = targetAddress;
-            return result;
-        }
-
-        public IndirectCallOp(Object targetMethod, CiValue result, CiValue[] parameters, CiValue targetAddress, LIRDebugInfo info, Map<XirMark, Mark> marks) {
-            super("CALL_INDIRECT", new CiValue[] {result}, info, concat(parameters, targetAddress), LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-            this.targetMethod = targetMethod;
-            this.marks = marks;
-        }
-
-        private CiValue targetAddress() {
-            return input(inputs.length - 1);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            callAlignment(tasm, masm);
-            if (marks != null) {
-                marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0]));
-            }
-            indirectCall(tasm, masm, asRegister(targetAddress()), targetMethod, info);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            } else if (mode == OperandMode.Output) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static void callAlignment(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        if (GraalOptions.AlignCallsForPatching) {
-            // make sure that the displacement word of the call ends up word aligned
-            int offset = masm.codeBuffer.position();
-            offset += tasm.target.arch.machineCodeCallDisplacementOffset;
-            while (offset++ % tasm.target.wordSize != 0) {
-                masm.nop();
-            }
-        }
-    }
-
-    public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRDebugInfo info) {
-        int before = masm.codeBuffer.position();
-        if (target instanceof CiRuntimeCall) {
-            long maxOffset = tasm.runtime.getMaxCallTargetOffset((CiRuntimeCall) target);
-            if (maxOffset != (int) maxOffset) {
-                // offset might not fit a 32-bit immediate, generate an
-                // indirect call with a 64-bit immediate
-                CiRegister scratch = tasm.frameMap.registerConfig.getScratchRegister();
-                // TODO(cwi): we want to get rid of a generally reserved scratch register.
-                masm.movq(scratch, 0L);
-                masm.call(scratch);
-            } else {
-                masm.call();
-            }
-        } else {
-            masm.call();
-        }
-        int after = masm.codeBuffer.position();
-        tasm.recordDirectCall(before, after, tasm.runtime.asCallTarget(target), info);
-        tasm.recordExceptionHandlers(after, info);
-        masm.ensureUniquePC();
-    }
-
-    public static void directJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target) {
-        int before = masm.codeBuffer.position();
-        masm.jmp(0, true);
-        int after = masm.codeBuffer.position();
-        tasm.recordDirectCall(before, after, tasm.runtime.asCallTarget(target), null);
-        masm.ensureUniquePC();
-    }
-
-    public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiRegister dst, Object target, LIRDebugInfo info) {
-        int before = masm.codeBuffer.position();
-        masm.call(dst);
-        int after = masm.codeBuffer.position();
-        tasm.recordIndirectCall(before, after, tasm.runtime.asCallTarget(target), info);
-        tasm.recordExceptionHandlers(after, info);
-        masm.ensureUniquePC();
-    }
-
-    public static void shouldNotReachHere(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        if (GraalOptions.GenAssertionCode) {
-            directCall(tasm, masm, CiRuntimeCall.Debug, null);
-            masm.hlt();
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Compare.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.target.amd64;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.util.*;
-
-public enum AMD64Compare {
-    ICMP, LCMP, ACMP, FCMP, DCMP;
-
-    public static class CompareOp extends AMD64LIRInstruction {
-        public CompareOp(AMD64Compare opcode, CiValue x, CiValue y) {
-            super(opcode, LIRInstruction.NO_OPERANDS, null, new CiValue[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            CiValue x = input(0);
-            CiValue y = input(1);
-            emit(tasm, masm, (AMD64Compare) code, x, y);
-        }
-
-        @Override
-        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Input && index == 1) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            }
-            throw Util.shouldNotReachHere();
-        }
-
-        @Override
-        protected void verify() {
-            CiValue x = input(0);
-            CiValue y = input(1);
-
-            super.verify();
-            assert (name().startsWith("I") && x.kind == CiKind.Int && y.kind.stackKind() == CiKind.Int)
-                || (name().startsWith("I") && x.kind == CiKind.Jsr && y.kind == CiKind.Jsr)
-                || (name().startsWith("L") && x.kind == CiKind.Long && y.kind == CiKind.Long)
-                || (name().startsWith("A") && x.kind == CiKind.Object && y.kind == CiKind.Object)
-                || (name().startsWith("F") && x.kind == CiKind.Float && y.kind == CiKind.Float)
-                || (name().startsWith("D") && x.kind == CiKind.Double && y.kind == CiKind.Double);
-        }
-    }
-
-    protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Compare opcode, CiValue x, CiValue y) {
-        if (isRegister(y)) {
-            switch (opcode) {
-                case ICMP: masm.cmpl(asIntReg(x), asIntReg(y)); break;
-                case LCMP: masm.cmpq(asLongReg(x), asLongReg(y)); break;
-                case ACMP: masm.cmpptr(asObjectReg(x), asObjectReg(y)); break;
-                case FCMP: masm.ucomiss(asFloatReg(x), asFloatReg(y)); break;
-                case DCMP: masm.ucomisd(asDoubleReg(x), asDoubleReg(y)); break;
-                default:   throw Util.shouldNotReachHere();
-            }
-        } else if (isConstant(y)) {
-            switch (opcode) {
-                case ICMP: masm.cmpl(asIntReg(x), tasm.asIntConst(y)); break;
-                case LCMP: masm.cmpq(asLongReg(x), tasm.asIntConst(y)); break;
-                case ACMP:
-                    if (((CiConstant) y).isNull()) {
-                        masm.cmpq(asObjectReg(x), 0); break;
-                    } else {
-                        throw Util.shouldNotReachHere("Only null object constants are allowed in comparisons");
-                    }
-                case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(y)); break;
-                case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(y)); break;
-                default:   throw Util.shouldNotReachHere();
-            }
-        } else {
-            switch (opcode) {
-                case ICMP: masm.cmpl(asIntReg(x), tasm.asIntAddr(y)); break;
-                case LCMP: masm.cmpq(asLongReg(x), tasm.asLongAddr(y)); break;
-                case ACMP: masm.cmpptr(asObjectReg(x), tasm.asObjectAddr(y)); break;
-                case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatAddr(y)); break;
-                case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleAddr(y)); break;
-                default:  throw Util.shouldNotReachHere();
-            }
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompareToIntOpcode.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.target.amd64;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.asm.*;
-import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.util.*;
-
-/**
- * Implementation of the Java bytecodes that compare a long, float, or double value and produce the
- * integer constants -1, 0, 1 on less, equal, or greater, respectively.  For floating point compares,
- * unordered can be either greater {@link #CMP2INT_UG} or less {@link #CMP2INT_UL}.
- */
-public enum AMD64CompareToIntOpcode {
-    CMP2INT, CMP2INT_UG, CMP2INT_UL;
-
-    public LIRInstruction create(CiValue result) {
-        CiValue[] outputs = new CiValue[] {result};
-
-        return new AMD64LIRInstruction(this, outputs, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) {
-            @Override
-            public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-                emit(masm, output(0));
-            }
-
-            @Override
-            protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-                if (mode == OperandMode.Output && index == 0) {
-                    return EnumSet.of(OperandFlag.Register);
-                }
-                throw Util.shouldNotReachHere();
-            }
-        };
-    }
-
-    private void emit(AMD64MacroAssembler masm, CiValue result) {
-        CiRegister dest = asIntReg(result);
-        Label high = new Label();
-        Label low = new Label();
-        Label done = new Label();
-
-        // comparison is done by a separate LIR instruction before
-        switch (this) {
-            case CMP2INT:
-                masm.jcc(ConditionFlag.greater, high);
-                masm.jcc(ConditionFlag.less, low);
-                break;
-            case CMP2INT_UG:
-                masm.jcc(ConditionFlag.parity, high);
-                masm.jcc(ConditionFlag.above, high);
-                masm.jcc(ConditionFlag.below, low);
-                break;
-            case CMP2INT_UL:
-                masm.jcc(ConditionFlag.parity, low);
-                masm.jcc(ConditionFlag.above, high);
-                masm.jcc(ConditionFlag.below, low);
-                break;
-            default:
-                throw Util.shouldNotReachHere();
-        }
-
-        // equal -> 0
-        masm.xorptr(dest, dest);
-        masm.jmp(done);
-
-        // greater -> 1
-        masm.bind(high);
-        masm.xorptr(dest, dest);
-        masm.incrementl(dest, 1);
-        masm.jmp(done);
-
-        // less -> -1
-        masm.bind(low);
-        masm.xorptr(dest, dest);
-        masm.decrementl(dest, 1);
-
-        masm.bind(done);
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,448 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.target.amd64;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.max.asm.*;
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ci.CiAddress.Scale;
-import com.oracle.max.cri.ci.CiTargetMethod.JumpTable;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.nodes.calc.*;
-
-public class AMD64ControlFlow {
-
-    public static class LabelOp extends AMD64LIRInstruction implements StandardOp.LabelOp {
-        private final Label label;
-        private final boolean align;
-
-        public LabelOp(Label label, boolean align) {
-            super("LABEL", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-            this.label = label;
-            this.align = align;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            if (align) {
-                masm.align(tasm.target.wordSize);
-            }
-            masm.bind(label);
-        }
-
-        @Override
-        public String operationString() {
-            return label.toString();
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            throw Util.shouldNotReachHere();
-        }
-
-        @Override
-        public Label getLabel() {
-            return label;
-        }
-    }
-
-
-    public static class ReturnOp extends AMD64LIRInstruction {
-        public ReturnOp(CiValue input) {
-            super("RETURN", LIRInstruction.NO_OPERANDS, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            masm.ret(0);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class JumpOp extends AMD64LIRInstruction implements StandardOp.JumpOp {
-        private final LabelRef destination;
-
-        public JumpOp(LabelRef destination, LIRDebugInfo info) {
-            super("JUMP", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-            this.destination = destination;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            masm.jmp(destination.label());
-        }
-
-        @Override
-        public LabelRef destination() {
-            return destination;
-        }
-
-        @Override
-        public String operationString() {
-            return  "[" + destination + "]";
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp {
-        protected Condition condition;
-        protected LabelRef destination;
-
-        public BranchOp(Condition condition, LabelRef destination, LIRDebugInfo info) {
-            super("BRANCH", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-            this.condition = condition;
-            this.destination = destination;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            masm.jcc(intCond(condition), destination.label());
-        }
-
-        @Override
-        public LabelRef destination() {
-            return destination;
-        }
-
-        @Override
-        public void negate(LabelRef newDestination) {
-            destination = newDestination;
-            condition = condition.negate();
-        }
-
-        @Override
-        public String operationString() {
-            return condition.operator + " [" + destination + "]";
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class FloatBranchOp extends BranchOp {
-        protected boolean unorderedIsTrue;
-
-        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination, LIRDebugInfo info) {
-            super(condition, destination, info);
-            this.unorderedIsTrue = unorderedIsTrue;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            floatJcc(masm, condition, unorderedIsTrue, destination.label());
-        }
-
-        @Override
-        public void negate(LabelRef newDestination) {
-            super.negate(newDestination);
-            unorderedIsTrue = !unorderedIsTrue;
-        }
-
-        @Override
-        public String operationString() {
-            return condition.operator + " [" + destination + "]" + (unorderedIsTrue ? " unorderedIsTrue" : " unorderedIsFalse");
-        }
-    }
-
-
-    public static class TableSwitchOp extends AMD64LIRInstruction {
-        private final int lowKey;
-        private final LabelRef defaultTarget;
-        private final LabelRef[] targets;
-
-        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) {
-            super("TABLE_SWITCH", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, new CiValue[] {index}, new CiValue[] {scratch});
-            this.lowKey = lowKey;
-            this.defaultTarget = defaultTarget;
-            this.targets = targets;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(alive(0)), asLongReg(temp(0)));
-        }
-
-        @Override
-        public String operationString() {
-            StringBuilder buf = new StringBuilder(super.operationString());
-            buf.append("\ndefault: [").append(defaultTarget).append(']');
-            int key = lowKey;
-            for (LabelRef l : targets) {
-                buf.append("\ncase ").append(key).append(": [").append(l).append(']');
-                key++;
-            }
-            return buf.toString();
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Temp && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class CondMoveOp extends AMD64LIRInstruction {
-        private final Condition condition;
-
-        public CondMoveOp(Variable result, Condition condition, Variable trueValue, CiValue falseValue) {
-            super("CMOVE", new CiValue[] {result}, null, new CiValue[] {falseValue}, new CiValue[] {trueValue}, LIRInstruction.NO_OPERANDS);
-            this.condition = condition;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            cmove(tasm, masm, output(0), false, condition, false, alive(0), input(0));
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw Util.shouldNotReachHere();
-        }
-
-        @Override
-        public String operationString() {
-            return condition.toString() + " " + super.operationString();
-        }
-    }
-
-
-    public static class FloatCondMoveOp extends AMD64LIRInstruction {
-        private final Condition condition;
-        private final boolean unorderedIsTrue;
-
-        public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
-            super("FLOAT_CMOVE", new CiValue[] {result}, null, LIRInstruction.NO_OPERANDS, new CiValue[] {trueValue, falseValue}, LIRInstruction.NO_OPERANDS);
-            this.condition = condition;
-            this.unorderedIsTrue = unorderedIsTrue;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            cmove(tasm, masm, output(0), true, condition, unorderedIsTrue, alive(0), alive(1));
-        }
-
-        @Override
-        public String operationString() {
-            return condition.toString() + " unordered=" + unorderedIsTrue + " " + super.operationString();
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Alive && index == 1) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    private static void tableswitch(TargetMethodAssembler tasm, AMD64MacroAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, CiRegister value, CiRegister scratch) {
-        Buffer buf = masm.codeBuffer;
-        // Compare index against jump table bounds
-        int highKey = lowKey + targets.length - 1;
-        if (lowKey != 0) {
-            // subtract the low value from the switch value
-            masm.subl(value, lowKey);
-            masm.cmpl(value, highKey - lowKey);
-        } else {
-            masm.cmpl(value, highKey);
-        }
-
-        // Jump to default target if index is not within the jump table
-        masm.jcc(ConditionFlag.above, defaultTarget.label());
-
-        // Set scratch to address of jump table
-        int leaPos = buf.position();
-        masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), 0));
-        int afterLea = buf.position();
-
-        // Load jump table entry into scratch and jump to it
-        masm.movslq(value, new CiAddress(CiKind.Int, scratch.asValue(), value.asValue(), Scale.Times4, 0));
-        masm.addq(scratch, value);
-        masm.jmp(scratch);
-
-        // Inserting padding so that jump table address is 4-byte aligned
-        if ((buf.position() & 0x3) != 0) {
-            masm.nop(4 - (buf.position() & 0x3));
-        }
-
-        // Patch LEA instruction above now that we know the position of the jump table
-        int jumpTablePos = buf.position();
-        buf.setPosition(leaPos);
-        masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), jumpTablePos - afterLea));
-        buf.setPosition(jumpTablePos);
-
-        // Emit jump table entries
-        for (LabelRef target : targets) {
-            Label label = target.label();
-            int offsetToJumpTableBase = buf.position() - jumpTablePos;
-            if (label.isBound()) {
-                int imm32 = label.position() - jumpTablePos;
-                buf.emitInt(imm32);
-            } else {
-                label.addPatchAt(buf.position());
-
-                buf.emitByte(0); // psuedo-opcode for jump table entry
-                buf.emitShort(offsetToJumpTableBase);
-                buf.emitByte(0); // padding to make jump table entry 4 bytes wide
-            }
-        }
-
-        JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4);
-        tasm.targetMethod.addAnnotation(jt);
-    }
-
-    private static void floatJcc(AMD64MacroAssembler masm, Condition condition, boolean unorderedIsTrue, Label label) {
-        ConditionFlag cond = floatCond(condition);
-        Label endLabel = new Label();
-        if (unorderedIsTrue && !trueOnUnordered(cond)) {
-            masm.jcc(ConditionFlag.parity, label);
-        } else if (!unorderedIsTrue && trueOnUnordered(cond)) {
-            masm.jcc(ConditionFlag.parity, endLabel);
-        }
-        masm.jcc(cond, label);
-        masm.bind(endLabel);
-    }
-
-    private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, boolean isFloat, Condition condition, boolean unorderedIsTrue, CiValue trueValue, CiValue falseValue) {
-        ConditionFlag cond = isFloat ? floatCond(condition) : intCond(condition);
-        // check that we don't overwrite an input operand before it is used.
-        assert !result.equals(trueValue);
-
-        AMD64Move.move(tasm, masm, result, falseValue);
-        cmove(tasm, masm, result, cond, trueValue);
-
-        if (isFloat) {
-            if (unorderedIsTrue && !trueOnUnordered(cond)) {
-                cmove(tasm, masm, result, ConditionFlag.parity, trueValue);
-            } else if (!unorderedIsTrue && trueOnUnordered(cond)) {
-                cmove(tasm, masm, result, ConditionFlag.parity, falseValue);
-            }
-        }
-    }
-
-    private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, ConditionFlag cond, CiValue other) {
-        if (isRegister(other)) {
-            assert asRegister(other) != asRegister(result) : "other already overwritten by previous move";
-            switch (other.kind) {
-                case Int:  masm.cmovl(cond, asRegister(result), asRegister(other)); break;
-                case Long: masm.cmovq(cond, asRegister(result), asRegister(other)); break;
-                default:   throw Util.shouldNotReachHere();
-            }
-        } else {
-            switch (other.kind) {
-                case Int:  masm.cmovl(cond, asRegister(result), tasm.asAddress(other)); break;
-                case Long: masm.cmovq(cond, asRegister(result), tasm.asAddress(other)); break;
-                default:   throw Util.shouldNotReachHere();
-            }
-        }
-    }
-
-    private static ConditionFlag intCond(Condition cond) {
-        switch (cond) {
-            case EQ: return ConditionFlag.equal;
-            case NE: return ConditionFlag.notEqual;
-            case LT: return ConditionFlag.less;
-            case LE: return ConditionFlag.lessEqual;
-            case GE: return ConditionFlag.greaterEqual;
-            case GT: return ConditionFlag.greater;
-            case BE: return ConditionFlag.belowEqual;
-            case AE: return ConditionFlag.aboveEqual;
-            case AT: return ConditionFlag.above;
-            case BT: return ConditionFlag.below;
-            case OF: return ConditionFlag.overflow;
-            case NOF: return ConditionFlag.noOverflow;
-            default: throw Util.shouldNotReachHere();
-        }
-    }
-
-    private static ConditionFlag floatCond(Condition cond) {
-        switch (cond) {
-            case EQ: return ConditionFlag.equal;
-            case NE: return ConditionFlag.notEqual;
-            case BT: return ConditionFlag.below;
-            case BE: return ConditionFlag.belowEqual;
-            case AE: return ConditionFlag.aboveEqual;
-            case AT: return ConditionFlag.above;
-            default: throw Util.shouldNotReachHere();
-        }
-    }
-
-    private static boolean trueOnUnordered(ConditionFlag condition) {
-        switch(condition) {
-            case aboveEqual:
-            case notEqual:
-            case above:
-            case less:
-            case overflow:
-                return false;
-            case equal:
-            case belowEqual:
-            case below:
-            case greaterEqual:
-            case noOverflow:
-                return true;
-            default:
-                throw Util.shouldNotReachHere();
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Wed Feb 08 21:15:00 2012 -0800
@@ -28,9 +28,10 @@
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.amd64.*;
+import com.oracle.max.graal.lir.asm.*;
 import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction;
 
 public class AMD64DeoptimizationStub extends AMD64SlowPath {
@@ -79,7 +80,7 @@
                 code = 4;
                 break;
             default:
-                throw Util.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
         masm.movq(scratch, code);
         // TODO Why use scratch register here? Is it an implicit calling convention that the runtime function reads this register?
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Feb 08 21:15:00 2012 -0800
@@ -24,9 +24,9 @@
 package com.oracle.max.graal.compiler.target.amd64;
 
 import static com.oracle.max.cri.ci.CiValueUtil.*;
-import static com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.*;
-import static com.oracle.max.graal.compiler.target.amd64.AMD64Compare.*;
-import static com.oracle.max.graal.compiler.target.amd64.AMD64CompareToIntOpcode.*;
+import static com.oracle.max.graal.lir.amd64.AMD64Arithmetic.*;
+import static com.oracle.max.graal.lir.amd64.AMD64Compare.*;
+import static com.oracle.max.graal.lir.amd64.AMD64CompareToIntOpcode.*;
 
 import java.util.*;
 
@@ -38,35 +38,35 @@
 import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
 import com.oracle.max.cri.xir.*;
 import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.DivOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op1Reg;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op1Stack;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op2Reg;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op2Stack;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.ShiftOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Call.DirectCallOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Call.IndirectCallOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Compare.CompareOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.BranchOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.CondMoveOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.FloatBranchOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.FloatCondMoveOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.JumpOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.LabelOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.ReturnOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.TableSwitchOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Move.CompareAndSwapOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Move.LeaOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Move.LoadOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Move.MembarOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Move.MoveFromRegOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Move.MoveToRegOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Move.NullCheckOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Move.SpillMoveOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Move.StoreOp;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.StandardOp.JumpOp;
+import com.oracle.max.graal.lir.StandardOp.LabelOp;
+import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.DivOp;
+import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.Op1Reg;
+import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.Op1Stack;
+import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.Op2Reg;
+import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.Op2Stack;
+import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.ShiftOp;
+import com.oracle.max.graal.lir.amd64.AMD64Call.DirectCallOp;
+import com.oracle.max.graal.lir.amd64.AMD64Call.IndirectCallOp;
+import com.oracle.max.graal.lir.amd64.AMD64Compare.CompareOp;
+import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.BranchOp;
+import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
+import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.FloatBranchOp;
+import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.FloatCondMoveOp;
+import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.ReturnOp;
+import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp;
+import com.oracle.max.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
+import com.oracle.max.graal.lir.amd64.AMD64Move.LeaOp;
+import com.oracle.max.graal.lir.amd64.AMD64Move.LoadOp;
+import com.oracle.max.graal.lir.amd64.AMD64Move.MembarOp;
+import com.oracle.max.graal.lir.amd64.AMD64Move.MoveFromRegOp;
+import com.oracle.max.graal.lir.amd64.AMD64Move.MoveToRegOp;
+import com.oracle.max.graal.lir.amd64.AMD64Move.NullCheckOp;
+import com.oracle.max.graal.lir.amd64.AMD64Move.SpillMoveOp;
+import com.oracle.max.graal.lir.amd64.AMD64Move.StoreOp;
 import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.calc.*;
@@ -222,7 +222,7 @@
             case Object: append(new BranchOp(cond, label, info)); break;
             case Float:
             case Double: append(new FloatBranchOp(cond, unorderedIsTrue, label, info)); break;
-            default: throw Util.shouldNotReachHere("" + left.kind);
+            default: throw GraalInternalError.shouldNotReachHere("" + left.kind);
         }
     }
 
@@ -253,7 +253,7 @@
             case Object: append(new CompareOp(ACMP, left, right)); break;
             case Float: append(new CompareOp(FCMP, left, right)); break;
             case Double: append(new CompareOp(DCMP, left, right)); break;
-            default: throw Util.shouldNotReachHere();
+            default: throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -265,7 +265,7 @@
             case Long:   append(new Op1Stack(LNEG, result, input)); break;
             case Float:  append(new Op2Reg(FXOR, result, input, CiConstant.forFloat(Float.intBitsToFloat(0x80000000)))); break;
             case Double: append(new Op2Reg(DXOR, result, input, CiConstant.forDouble(Double.longBitsToDouble(0x8000000000000000L)))); break;
-            default: throw Util.shouldNotReachHere();
+            default: throw GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
@@ -278,7 +278,7 @@
             case Long:   append(new Op2Stack(LADD, result, a, loadNonConst(b))); break;
             case Float:  append(new Op2Stack(FADD, result, a, loadNonConst(b))); break;
             case Double: append(new Op2Stack(DADD, result, a, loadNonConst(b))); break;
-            default:     throw Util.shouldNotReachHere();
+            default:     throw GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
@@ -291,7 +291,7 @@
             case Long:   append(new Op2Stack(LSUB, result, a, loadNonConst(b))); break;
             case Float:  append(new Op2Stack(FSUB, result, a, loadNonConst(b))); break;
             case Double: append(new Op2Stack(DSUB, result, a, loadNonConst(b))); break;
-            default:     throw Util.shouldNotReachHere();
+            default:     throw GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
@@ -304,7 +304,7 @@
             case Long:   append(new Op2Reg(LMUL, result, a, loadNonConst(b))); break;
             case Float:  append(new Op2Stack(FMUL, result, a, loadNonConst(b))); break;
             case Double: append(new Op2Stack(DMUL, result, a, loadNonConst(b))); break;
-            default:     throw Util.shouldNotReachHere();
+            default:     throw GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
@@ -331,7 +331,7 @@
                 return result;
             }
             default:
-                throw Util.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -351,7 +351,7 @@
             case Double:
                 return emitCallToRuntime(CiRuntimeCall.ArithmeticDrem, false, a, b);
             default:
-                throw Util.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -367,7 +367,7 @@
                 append(new DivOp(LUDIV, RAX_L, RAX_L, load(b), state()));
                 return emitMove(RAX_L);
             default:
-                throw Util.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -383,7 +383,7 @@
                 append(new DivOp(LUREM, RDX_L, RAX_L, load(b), state()));
                 return emitMove(RDX_L);
             default:
-                throw Util.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -394,7 +394,7 @@
         switch(a.kind) {
             case Int:    append(new Op2Stack(IAND, result, a, loadNonConst(b))); break;
             case Long:   append(new Op2Stack(LAND, result, a, loadNonConst(b))); break;
-            default:     throw Util.shouldNotReachHere();
+            default:     throw GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
@@ -405,7 +405,7 @@
         switch(a.kind) {
             case Int:    append(new Op2Stack(IOR, result, a, loadNonConst(b))); break;
             case Long:   append(new Op2Stack(LOR, result, a, loadNonConst(b))); break;
-            default:     throw Util.shouldNotReachHere();
+            default:     throw GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
@@ -416,7 +416,7 @@
         switch(a.kind) {
             case Int:    append(new Op2Stack(IXOR, result, a, loadNonConst(b))); break;
             case Long:   append(new Op2Stack(LXOR, result, a, loadNonConst(b))); break;
-            default:     throw Util.shouldNotReachHere();
+            default:     throw GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
@@ -428,7 +428,7 @@
         switch (a.kind) {
             case Int:    append(new ShiftOp(ISHL, result, a, loadShiftCount(b))); break;
             case Long:   append(new ShiftOp(LSHL, result, a, loadShiftCount(b))); break;
-            default: Util.shouldNotReachHere();
+            default: GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
@@ -439,7 +439,7 @@
         switch (a.kind) {
             case Int:    append(new ShiftOp(ISHR, result, a, loadShiftCount(b))); break;
             case Long:   append(new ShiftOp(LSHR, result, a, loadShiftCount(b))); break;
-            default: Util.shouldNotReachHere();
+            default: GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
@@ -450,7 +450,7 @@
         switch (a.kind) {
             case Int:    append(new ShiftOp(IUSHR, result, a, loadShiftCount(b))); break;
             case Long:   append(new ShiftOp(LUSHR, result, a, loadShiftCount(b))); break;
-            default: Util.shouldNotReachHere();
+            default: GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
@@ -489,7 +489,7 @@
             case MOV_L2D: append(new Op1Reg(MOV_L2D, result, input)); break;
             case MOV_F2I: append(new Op1Reg(MOV_F2I, result, input)); break;
             case MOV_D2L: append(new Op1Reg(MOV_D2L, result, input)); break;
-            default: throw Util.shouldNotReachHere();
+            default: throw GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
@@ -618,7 +618,7 @@
                 append(CMP2INT.create(result));
                 break;
             default:
-                throw Util.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
         setResult(x, result);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRInstruction.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.target.amd64;
-
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-
-/**
- * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method.
- */
-public abstract class AMD64LIRInstruction extends LIRInstruction {
-
-    public AMD64LIRInstruction(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) {
-        super(opcode, outputs, info, inputs, alives, temps);
-    }
-
-    @Override
-    public final void emitCode(TargetMethodAssembler tasm) {
-        emitCode(tasm, (AMD64MacroAssembler) tasm.asm);
-    }
-
-    public abstract void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm);
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MethodEndStub.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MethodEndStub.java	Wed Feb 08 21:15:00 2012 -0800
@@ -24,7 +24,8 @@
 
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.asm.*;
+import com.oracle.max.graal.lir.amd64.*;
+import com.oracle.max.graal.lir.asm.*;
 
 public class AMD64MethodEndStub extends AMD64SlowPath {
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Move.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,485 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.target.amd64;
-
-import static com.oracle.max.cri.ci.CiValueUtil.*;
-import static java.lang.Double.*;
-import static java.lang.Float.*;
-
-import java.util.*;
-
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.StandardOp.MoveOp;
-import com.oracle.max.graal.compiler.util.*;
-
-public class AMD64Move {
-
-    public static class SpillMoveOp extends AMD64LIRInstruction implements MoveOp {
-        public SpillMoveOp(CiValue result, CiValue input) {
-            super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            move(tasm, masm, getResult(), getInput());
-        }
-
-        @Override
-        public CiValue getInput() {
-            return input(0);
-        }
-        @Override
-        public CiValue getResult() {
-            return output(0);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp {
-        public MoveToRegOp(CiValue result, CiValue input) {
-            super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            move(tasm, masm, getResult(), getInput());
-        }
-
-        @Override
-        public CiValue getInput() {
-            return input(0);
-        }
-        @Override
-        public CiValue getResult() {
-            return output(0);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp {
-        public MoveFromRegOp(CiValue result, CiValue input) {
-            super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            move(tasm, masm, getResult(), getInput());
-        }
-
-        @Override
-        public CiValue getInput() {
-            return input(0);
-        }
-        @Override
-        public CiValue getResult() {
-            return output(0);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.RegisterHint);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class LoadOp extends AMD64LIRInstruction {
-        public LoadOp(CiValue result, CiValue address, LIRDebugInfo info) {
-            super("LOAD", new CiValue[] {result}, info, new CiValue[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            load(tasm, masm, output(0), (CiAddress) input(0), info);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Address);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class StoreOp extends AMD64LIRInstruction {
-        public StoreOp(CiValue address, CiValue input, LIRDebugInfo info) {
-            super("STORE", LIRInstruction.NO_OPERANDS, info, new CiValue[] {address, input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            store(tasm, masm, (CiAddress) input(0), input(1), info);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Address);
-            } else if (mode == OperandMode.Input && index == 1) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class LeaOp extends AMD64LIRInstruction {
-        public LeaOp(CiValue result, CiValue address) {
-            super("LEA", new CiValue[] {result}, null, new CiValue[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            masm.leaq(asLongReg(output(0)), tasm.asAddress(input(0)));
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Address, OperandFlag.Stack, OperandFlag.Uninitialized);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class MembarOp extends AMD64LIRInstruction {
-        private final int barriers;
-
-        public MembarOp(final int barriers) {
-            super("MEMBAR", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-            this.barriers = barriers;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            masm.membar(barriers);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class NullCheckOp extends AMD64LIRInstruction {
-        public NullCheckOp(Variable input, LIRDebugInfo info) {
-            super("NULL_CHECK", LIRInstruction.NO_OPERANDS, info, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            tasm.recordImplicitException(masm.codeBuffer.position(), info);
-            masm.nullCheck(asRegister(input(0)));
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    public static class CompareAndSwapOp extends AMD64LIRInstruction {
-        public CompareAndSwapOp(CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) {
-            super("CAS", new CiValue[] {result}, null, new CiValue[] {address, cmpValue, newValue}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            compareAndSwap(tasm, masm, output(0), asAddress(input(0)), input(1), input(2));
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Address);
-            } else if (mode == OperandMode.Input && index == 1) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Input && index == 2) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    protected static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) {
-        if (isRegister(input)) {
-            if (isRegister(result)) {
-                reg2reg(masm, result, input);
-            } else if (isStackSlot(result)) {
-                reg2stack(tasm, masm, result, input);
-            } else {
-                throw Util.shouldNotReachHere();
-            }
-        } else if (isStackSlot(input)) {
-            if (isRegister(result)) {
-                stack2reg(tasm, masm, result, input);
-            } else {
-                throw Util.shouldNotReachHere();
-            }
-        } else if (isConstant(input)) {
-            if (isRegister(result)) {
-                const2reg(tasm, masm, result, (CiConstant) input);
-            } else if (isStackSlot(result)) {
-                const2stack(tasm, masm, result, (CiConstant) input);
-            } else {
-                throw Util.shouldNotReachHere();
-            }
-        } else {
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-    private static void reg2reg(AMD64MacroAssembler masm, CiValue result, CiValue input) {
-        if (input.equals(result)) {
-            return;
-        }
-        switch (result.kind) {
-            case Jsr:
-            case Int:    masm.movl(asRegister(result),    asRegister(input)); break;
-            case Long:   masm.movq(asRegister(result),    asRegister(input)); break;
-            case Float:  masm.movflt(asFloatReg(result),  asFloatReg(input)); break;
-            case Double: masm.movdbl(asDoubleReg(result), asDoubleReg(input)); break;
-            case Object: masm.movq(asRegister(result),    asRegister(input)); break;
-            default:     throw Util.shouldNotReachHere("kind=" + result.kind);
-        }
-    }
-
-    private static void reg2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) {
-        switch (result.kind) {
-            case Jsr:
-            case Int:    masm.movl(tasm.asAddress(result),   asRegister(input)); break;
-            case Long:   masm.movq(tasm.asAddress(result),   asRegister(input)); break;
-            case Float:  masm.movflt(tasm.asAddress(result), asFloatReg(input)); break;
-            case Double: masm.movsd(tasm.asAddress(result),  asDoubleReg(input)); break;
-            case Object: masm.movq(tasm.asAddress(result),   asRegister(input)); break;
-            default:     throw Util.shouldNotReachHere();
-        }
-    }
-
-    private static void stack2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) {
-        switch (result.kind) {
-            case Jsr:
-            case Int:    masm.movl(asRegister(result),    tasm.asAddress(input)); break;
-            case Long:   masm.movq(asRegister(result),    tasm.asAddress(input)); break;
-            case Float:  masm.movflt(asFloatReg(result),  tasm.asAddress(input)); break;
-            case Double: masm.movdbl(asDoubleReg(result), tasm.asAddress(input)); break;
-            case Object: masm.movq(asRegister(result),    tasm.asAddress(input)); break;
-            default:     throw Util.shouldNotReachHere();
-        }
-    }
-
-    private static void const2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) {
-        switch (result.kind) {
-            case Jsr:
-            case Int:
-                // Do not optimize with an XOR as this instruction may be between
-                // a CMP and a Jcc in which case the XOR will modify the condition
-                // flags and interfere with the Jcc.
-                masm.movl(asRegister(result), tasm.asIntConst(c));
-                break;
-            case Long:
-                // Do not optimize with an XOR as this instruction may be between
-                // a CMP and a Jcc in which case the XOR will modify the condition
-                // flags and interfere with the Jcc.
-                masm.movq(asRegister(result), c.asLong());
-                break;
-            case Float:
-                // This is *not* the same as 'constant == 0.0f' in the case where constant is -0.0f
-                if (Float.floatToRawIntBits(c.asFloat()) == Float.floatToRawIntBits(0.0f)) {
-                    masm.xorps(asFloatReg(result), asFloatReg(result));
-                } else {
-                    masm.movflt(asFloatReg(result), tasm.asFloatConstRef(c));
-                }
-                break;
-            case Double:
-                // This is *not* the same as 'constant == 0.0d' in the case where constant is -0.0d
-                if (Double.doubleToRawLongBits(c.asDouble()) == Double.doubleToRawLongBits(0.0d)) {
-                    masm.xorpd(asDoubleReg(result), asDoubleReg(result));
-                } else {
-                    masm.movdbl(asDoubleReg(result), tasm.asDoubleConstRef(c));
-                }
-                break;
-            case Object:
-                // Do not optimize with an XOR as this instruction may be between
-                // a CMP and a Jcc in which case the XOR will modify the condition
-                // flags and interfere with the Jcc.
-                if (c.isNull()) {
-                    masm.movq(asRegister(result), 0x0L);
-                } else if (tasm.target.inlineObjects) {
-                    tasm.recordDataReferenceInCode(c, 0);
-                    masm.movq(asRegister(result), 0xDEADDEADDEADDEADL);
-                } else {
-                    masm.movq(asRegister(result), tasm.recordDataReferenceInCode(c, 0));
-                }
-                break;
-            default:
-                throw Util.shouldNotReachHere();
-        }
-    }
-
-    private static void const2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) {
-        switch (result.kind) {
-            case Jsr:
-            case Int:    masm.movl(tasm.asAddress(result), c.asInt()); break;
-            case Long:   masm.movlong(tasm.asAddress(result), c.asLong()); break;
-            case Float:  masm.movl(tasm.asAddress(result), floatToRawIntBits(c.asFloat())); break;
-            case Double: masm.movlong(tasm.asAddress(result), doubleToRawLongBits(c.asDouble())); break;
-            case Object:
-                if (c.isNull()) {
-                    masm.movlong(tasm.asAddress(result), 0L);
-                } else {
-                    throw Util.shouldNotReachHere("Non-null object constants must be in register");
-                }
-                break;
-            default:
-                throw Util.shouldNotReachHere();
-        }
-    }
-
-
-    protected static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress loadAddr, LIRDebugInfo info) {
-        if (info != null) {
-            tasm.recordImplicitException(masm.codeBuffer.position(), info);
-        }
-        switch (loadAddr.kind) {
-            case Boolean:
-            case Byte:   masm.movsxb(asRegister(result),  loadAddr); break;
-            case Char:   masm.movzxl(asRegister(result),  loadAddr); break;
-            case Short:  masm.movswl(asRegister(result),  loadAddr); break;
-            case Int:    masm.movslq(asRegister(result),  loadAddr); break;
-            case Long:   masm.movq(asRegister(result),    loadAddr); break;
-            case Float:  masm.movflt(asFloatReg(result),  loadAddr); break;
-            case Double: masm.movdbl(asDoubleReg(result), loadAddr); break;
-            case Object: masm.movq(asRegister(result),    loadAddr); break;
-            default:     throw Util.shouldNotReachHere();
-        }
-    }
-
-    protected static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiAddress storeAddr, CiValue input, LIRDebugInfo info) {
-        if (info != null) {
-            tasm.recordImplicitException(masm.codeBuffer.position(), info);
-        }
-
-        if (isRegister(input)) {
-            switch (storeAddr.kind) {
-                case Boolean:
-                case Byte:   masm.movb(storeAddr,   asRegister(input)); break;
-                case Char:
-                case Short:  masm.movw(storeAddr,   asRegister(input)); break;
-                case Int:    masm.movl(storeAddr,   asRegister(input)); break;
-                case Long:   masm.movq(storeAddr,   asRegister(input)); break;
-                case Float:  masm.movflt(storeAddr, asFloatReg(input)); break;
-                case Double: masm.movsd(storeAddr,  asDoubleReg(input)); break;
-                case Object: masm.movq(storeAddr,   asRegister(input)); break;
-                default:     throw Util.shouldNotReachHere();
-            }
-        } else if (isConstant(input)) {
-            CiConstant c = (CiConstant) input;
-            switch (storeAddr.kind) {
-                case Boolean:
-                case Byte:   masm.movb(storeAddr, c.asInt() & 0xFF); break;
-                case Char:
-                case Short:  masm.movw(storeAddr, c.asInt() & 0xFFFF); break;
-                case Jsr:
-                case Int:    masm.movl(storeAddr, c.asInt()); break;
-                case Long:
-                    if (Util.isInt(c.asLong())) {
-                        masm.movslq(storeAddr, (int) c.asLong());
-                    } else {
-                        throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory");
-                    }
-                    break;
-                case Float:  masm.movl(storeAddr, floatToRawIntBits(c.asFloat())); break;
-                case Double: throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory");
-                case Object:
-                    if (c.isNull()) {
-                        masm.movptr(storeAddr, 0);
-                    } else {
-                        throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory");
-                    }
-                    break;
-                default:
-                    throw Util.shouldNotReachHere();
-            }
-
-        } else {
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-    protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) {
-        assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax;
-
-        if (tasm.target.isMP) {
-            masm.lock();
-        }
-        switch (cmpValue.kind) {
-            case Int:    masm.cmpxchgl(asRegister(newValue), address); break;
-            case Long:
-            case Object: masm.cmpxchgq(asRegister(newValue), address); break;
-            default:     throw Util.shouldNotReachHere();
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64SlowPath.java	Wed Feb 08 21:13:35 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * 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.oracle.max.graal.compiler.target.amd64;
-
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-
-/**
- * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method.
- */
-public abstract class AMD64SlowPath implements LIR.SlowPath {
-    @Override
-    public final void emitCode(TargetMethodAssembler tasm) {
-        emitCode(tasm, (AMD64MacroAssembler) tasm.asm);
-    }
-
-    public abstract void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm);
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirOp.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirOp.java	Wed Feb 08 21:15:00 2012 -0800
@@ -39,9 +39,10 @@
 import com.oracle.max.cri.xir.CiXirAssembler.XirLabel;
 import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.amd64.*;
+import com.oracle.max.graal.lir.asm.*;
 
 public class AMD64XirOp extends LIRXirInstruction {
     public AMD64XirOp(XirSnippet snippet, CiValue[] operands, CiValue outputOperand, CiValue[] inputs, CiValue[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex,
@@ -480,7 +481,7 @@
                     break;
                 }
                 default:
-                    throw Util.shouldNotReachHere("Unknown XIR operation " + inst.op);
+                    throw GraalInternalError.shouldNotReachHere("Unknown XIR operation " + inst.op);
             }
         }
     }
@@ -493,7 +494,7 @@
             case Long: code = longOp; break;
             case Float: code = floatOp; break;
             case Double: code = doubleOp; break;
-            default: throw Util.shouldNotReachHere();
+            default: throw GraalInternalError.shouldNotReachHere();
         }
         assert left == result;
         if (isRegister(right) && right.kind != result.kind) {
@@ -514,7 +515,7 @@
             case Object: code = AMD64Compare.ACMP; break;
             case Float: code = AMD64Compare.FCMP; break;
             case Double: code = AMD64Compare.DCMP; break;
-            default: throw Util.shouldNotReachHere();
+            default: throw GraalInternalError.shouldNotReachHere();
         }
         AMD64Compare.emit(tasm, masm, code, x, y);
         masm.jcc(cflag, label);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java	Wed Feb 08 21:15:00 2012 -0800
@@ -42,22 +42,6 @@
     public static final char SUB_SECTION_CHARACTER = '=';
     public static final char SEPERATOR_CHARACTER = '-';
 
-    public static RuntimeException unimplemented() {
-        throw new GraalInternalError("unimplemented");
-    }
-
-    public static RuntimeException unimplemented(String msg, Object... args) {
-        throw new GraalInternalError("unimplemented: " + msg, args);
-    }
-
-    public static RuntimeException shouldNotReachHere() {
-        throw new GraalInternalError("should not reach here");
-    }
-
-    public static RuntimeException shouldNotReachHere(String msg, Object... args) {
-        throw new GraalInternalError("should not reach here: " + msg, args);
-    }
-
     public static <T> boolean replaceInList(T a, T b, List<T> list) {
         final int max = list.size();
         for (int i = 0; i < max; i++) {
--- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java	Wed Feb 08 21:15:00 2012 -0800
@@ -26,8 +26,8 @@
 import java.util.*;
 import java.util.concurrent.*;
 
+public class Debug {
 
-public class Debug {
     private static boolean ENABLED = false;
 
     public static void enable() {
@@ -73,7 +73,7 @@
 
     public static void scope(String name, Object context, Runnable runnable) {
         if (ENABLED) {
-            DebugScope.getInstance().scope(name, runnable, null, false, new Object[]{context});
+            DebugScope.getInstance().scope(name, runnable, null, false, new Object[] {context});
         } else {
             runnable.run();
         }
@@ -89,7 +89,7 @@
 
     public static <T> T scope(String name, Object context, Callable<T> callable) {
         if (ENABLED) {
-            return DebugScope.getInstance().scope(name, null, callable, false, new Object[]{context});
+            return DebugScope.getInstance().scope(name, null, callable, false, new Object[] {context});
         } else {
             return DebugScope.call(callable);
         }
@@ -130,6 +130,18 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
+    public static <T> T contextLookup(Class<T> clazz) {
+        if (ENABLED) {
+            for (Object o : context()) {
+                if (clazz.isInstance(o)) {
+                    return ((T) o);
+                }
+            }
+        }
+        return null;
+    }
+
     public static DebugMetric metric(String name) {
         if (ENABLED) {
             return new MetricImpl(name);
@@ -168,8 +180,8 @@
             }
 
             @Override
-            public RuntimeException interceptException(RuntimeException e) {
-                return e;
+            public RuntimeException interceptException(Throwable e) {
+                return null;
             }
 
             @Override
@@ -180,8 +192,12 @@
     }
 
     private static final DebugMetric VOID_METRIC = new DebugMetric() {
-        public void increment() { }
-        public void add(int value) { }
+
+        public void increment() {
+        }
+
+        public void add(int value) {
+        }
     };
 
     public static DebugTimer timer(String name) {
@@ -193,6 +209,9 @@
     }
 
     private static final DebugTimer VOID_TIMER = new DebugTimer() {
-        public TimerCloseable start() { return TimerImpl.VOID_CLOSEABLE; }
+
+        public TimerCloseable start() {
+            return TimerImpl.VOID_CLOSEABLE;
+        }
     };
 }
--- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/DebugConfig.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/DebugConfig.java	Wed Feb 08 21:15:00 2012 -0800
@@ -30,6 +30,6 @@
     boolean isMeterEnabled();
     boolean isDumpEnabled();
     boolean isTimeEnabled();
-    RuntimeException interceptException(RuntimeException e);
+    RuntimeException interceptException(Throwable e);
     Collection<? extends DebugDumpHandler> dumpHandlers();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/DebugDumpScope.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.debug;
+
+public final class DebugDumpScope {
+
+    private final String name;
+
+    public DebugDumpScope(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
--- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/internal/DebugScope.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/internal/DebugScope.java	Wed Feb 08 21:15:00 2012 -0800
@@ -32,7 +32,7 @@
 
     private static ThreadLocal<DebugScope> instanceTL = new ThreadLocal<>();
     private static ThreadLocal<DebugConfig> configTL = new ThreadLocal<>();
-    private static ThreadLocal<RuntimeException> lastExceptionThrownTL = new ThreadLocal<>();
+    private static ThreadLocal<Throwable> lastExceptionThrownTL = new ThreadLocal<>();
     private static DebugTimer scopeTime = Debug.timer("ScopeTime");
     private static DebugMetric scopeCount = Debug.metric("ScopeCount");
 
@@ -73,6 +73,7 @@
         this.parent = parent;
         this.context = context;
         this.qualifiedName = qualifiedName;
+        assert context != null;
     }
 
     public boolean isDumpEnabled() {
@@ -128,7 +129,7 @@
             if (!sandbox && newChild.hasValueMap()) {
                 getValueMap().addChild(newChild.getValueMap());
             }
-            newChild.deactivate();
+            newChild.context = null;
             instanceTL.set(oldContext);
             setConfig(oldConfig);
         }
@@ -142,13 +143,18 @@
             if (callable != null) {
                 return call(callable);
             }
-        } catch (RuntimeException e) {
+        } catch (Throwable e) {
             if (e == lastExceptionThrownTL.get()) {
                 throw e;
             } else {
                 RuntimeException newException = interceptException(e);
-                lastExceptionThrownTL.set(newException);
-                throw newException;
+                if (newException == null) {
+                    lastExceptionThrownTL.set(e);
+                    throw e;
+                } else {
+                    lastExceptionThrownTL.set(newException);
+                    throw newException;
+                }
             }
         }
         return null;
@@ -169,11 +175,7 @@
         }
     }
 
-    private void deactivate() {
-        context = null;
-    }
-
-    private RuntimeException interceptException(final RuntimeException e) {
+    private RuntimeException interceptException(final Throwable e) {
         final DebugConfig config = getConfig();
         if (config != null) {
             return scope("InterceptException", null, new Callable<RuntimeException>() {
@@ -183,12 +185,12 @@
                     try {
                         return config.interceptException(e);
                     } catch (Throwable t) {
-                        return e;
+                        return new RuntimeException("Exception while intercepting exception", e);
                     }
                 }
             }, false, new Object[] {e});
         }
-        return e;
+        return null;
     }
 
     private DebugValueMap getValueMap() {
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/GraalInternalError.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/GraalInternalError.java	Wed Feb 08 21:15:00 2012 -0800
@@ -30,13 +30,30 @@
 public class GraalInternalError extends Error {
 
     /**
-     * 
+     *
      */
     private static final long serialVersionUID = 8776065085829593278L;
     private Node node;
     private Graph graph;
     private final ArrayList<String> context = new ArrayList<>();
 
+    public static RuntimeException unimplemented() {
+        throw new GraalInternalError("unimplemented");
+    }
+
+    public static RuntimeException unimplemented(String msg) {
+        throw new GraalInternalError("unimplemented: %s", msg);
+    }
+
+    public static RuntimeException shouldNotReachHere() {
+        throw new GraalInternalError("should not reach here");
+    }
+
+    public static RuntimeException shouldNotReachHere(String msg) {
+        throw new GraalInternalError("should not reach here: %s", msg);
+    }
+
+
     /**
      * This constructor creates a {@link GraalInternalError} with a message assembled via {@link String#format(String, Object...)}.
      * It always uses the ENGLISH locale in order to always generate the same output.
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/Compiler.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/Compiler.java	Wed Feb 08 21:15:00 2012 -0800
@@ -34,7 +34,7 @@
     CompilerToVM getVMEntries();
     VMToCompiler getVMExits();
     GraalCompiler getCompiler();
-    RiType lookupType(String returnType, HotSpotTypeResolved accessingClass);
+    RiType lookupType(String returnType, HotSpotTypeResolved accessingClass, boolean eagerResolve);
     HotSpotVMConfig getConfig();
     GraalRuntime getRuntime();
     CiTarget getTarget();
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/CompilerImpl.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/CompilerImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -176,7 +176,7 @@
     }
 
     @Override
-    public RiType lookupType(String returnType, HotSpotTypeResolved accessingClass) {
+    public RiType lookupType(String returnType, HotSpotTypeResolved accessingClass, boolean eagerResolve) {
         if (returnType.length() == 1 && vmExits instanceof VMToCompilerImpl) {
             VMToCompilerImpl exitsNative = (VMToCompilerImpl) vmExits;
             CiKind kind = CiKind.fromPrimitiveOrVoidTypeChar(returnType.charAt(0));
@@ -207,7 +207,7 @@
                     return exitsNative.typeVoid;
             }
         }
-        return vmEntries.RiSignature_lookupType(returnType, accessingClass);
+        return vmEntries.RiSignature_lookupType(returnType, accessingClass, eagerResolve);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java	Wed Feb 08 21:15:00 2012 -0800
@@ -49,6 +49,7 @@
         this.dumpFilter = dumpFilter;
         this.methodFilter = methodFilter;
         dumpHandlers.add(new IdealGraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintIdealGraphPort));
+        dumpHandlers.add(new CFGPrinterObserver());
     }
 
     public boolean isLogEnabled() {
@@ -120,9 +121,9 @@
     }
 
     @Override
-    public RuntimeException interceptException(RuntimeException e) {
+    public RuntimeException interceptException(Throwable e) {
         if (e instanceof CiBailout) {
-            return e;
+            return null;
         }
         Debug.setConfig(Debug.fixedConfig(true, true, false, false, dumpHandlers));
         // sync "Exception occured in scope: " with mx/sanitycheck.py::Test.__init__
@@ -135,7 +136,7 @@
                 Debug.dump(o, "Exception graph");
             }
         }
-        return e;
+        return null;
     }
 
     @Override
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java	Wed Feb 08 21:15:00 2012 -0800
@@ -53,7 +53,7 @@
 
     boolean HotSpotMethodData_isMature(HotSpotMethodData methodData);
 
-    RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass);
+    RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass, boolean eagerResolve);
 
     Object RiConstantPool_lookupConstant(HotSpotTypeResolved pool, int cpi);
 
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -60,7 +60,7 @@
     public native int RiMethod_invocationCount(HotSpotMethodResolved method);
 
     @Override
-    public native RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass);
+    public native RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass, boolean eagerResolve);
 
     @Override
     public native Object RiConstantPool_lookupConstant(HotSpotTypeResolved pool, int cpi);
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -239,19 +239,13 @@
                     // to add something to its own queue.
                     return;
                 }
-            } else {
-                if (GraalOptions.Debug) {
-                    Debug.enable();
-                    HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter);
-                    Debug.setConfig(hotspotDebugConfig);
-                }
             }
 
             Runnable runnable = new Runnable() {
 
                 public void run() {
                     try {
-                        PhasePlan plan = getDefaultPhasePlan();
+                        final PhasePlan plan = getDefaultPhasePlan();
                         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime());
                         plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                         long startTime = 0;
@@ -265,7 +259,12 @@
                         CiTargetMethod result = null;
                         TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);
                         try {
-                            result = compiler.getCompiler().compileMethod(method, -1, plan);
+                            result = Debug.scope("Compiling", method, new Callable<CiTargetMethod>() {
+                                @Override
+                                public CiTargetMethod call() throws Exception {
+                                    return compiler.getCompiler().compileMethod(method, -1, plan);
+                                }
+                            });
                         } finally {
                             filter.remove();
                             if (printCompilation) {
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRegisterConfig.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRegisterConfig.java	Wed Feb 08 21:15:00 2012 -0800
@@ -28,10 +28,10 @@
 
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ci.CiCallingConvention.*;
-import com.oracle.max.cri.ci.CiRegister.*;
+import com.oracle.max.cri.ci.CiCallingConvention.Type;
+import com.oracle.max.cri.ci.CiRegister.RegisterFlag;
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.hotspot.*;
 
 public class HotSpotRegisterConfig implements RiRegisterConfig {
@@ -146,7 +146,7 @@
                     }
                     break;
                 default:
-                    throw Util.shouldNotReachHere();
+                    throw GraalInternalError.shouldNotReachHere();
             }
 
             if (locations[i] == null) {
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java	Wed Feb 08 21:15:00 2012 -0800
@@ -437,7 +437,7 @@
 
     private CiTargetMethod createCallbackStub(RiResolvedMethod method, CiGenericCallback callback) {
         StructuredGraph graph = new StructuredGraph();
-        FrameStateBuilder frameState = new FrameStateBuilder(method, method.maxLocals(), method.maxStackSize(), graph);
+        FrameStateBuilder frameState = new FrameStateBuilder(method, method.maxLocals(), method.maxStackSize(), graph, false);
         ValueNode local0 = frameState.loadLocal(0);
 
         FrameState initialFrameState = frameState.create(0);
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotSignature.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotSignature.java	Wed Feb 08 21:15:00 2012 -0800
@@ -117,13 +117,13 @@
     }
 
     @Override
-    public RiType argumentTypeAt(int index, RiType accessingClass) {
+    public RiType argumentTypeAt(int index, RiResolvedType accessingClass) {
         if (argumentTypes == null) {
             argumentTypes = new RiType[arguments.size()];
         }
         RiType type = argumentTypes[index];
         if (type == null) {
-            type = compiler.lookupType(arguments.get(index), (HotSpotTypeResolved) accessingClass);
+            type = compiler.lookupType(arguments.get(index), (HotSpotTypeResolved) accessingClass, false);
             argumentTypes[index] = type;
         }
         return type;
@@ -142,7 +142,7 @@
     @Override
     public RiType returnType(RiType accessingClass) {
         if (returnTypeCache == null) {
-            returnTypeCache = compiler.lookupType(returnType, (HotSpotTypeResolved) accessingClass);
+            returnTypeCache = compiler.lookupType(returnType, (HotSpotTypeResolved) accessingClass, false);
         }
         return returnTypeCache;
     }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypePrimitive.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypePrimitive.java	Wed Feb 08 21:15:00 2012 -0800
@@ -26,7 +26,7 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.hotspot.Compiler;
 
 /**
@@ -74,7 +74,7 @@
 
     @Override
     public CiConstant getEncoding(Representation r) {
-        throw Util.unimplemented("HotSpotTypePrimitive.getEncoding");
+        throw GraalInternalError.unimplemented("HotSpotTypePrimitive.getEncoding");
     }
 
     @Override
@@ -166,4 +166,9 @@
     public Class< ? > toJava() {
         return kind.toJavaClass();
     }
+
+    @Override
+    public RiResolvedType resolve(RiResolvedType accessingClass) {
+        return this;
+    }
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -253,4 +253,9 @@
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
         return toJava().getAnnotation(annotationClass);
     }
+
+    @Override
+    public RiResolvedType resolve(RiResolvedType accessingClass) {
+        return this;
+    }
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeUnresolved.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeUnresolved.java	Wed Feb 08 21:15:00 2012 -0800
@@ -31,9 +31,6 @@
  */
 public class HotSpotTypeUnresolved extends HotSpotType {
 
-    /**
-     * 
-     */
     private static final long serialVersionUID = -2320936267633521314L;
     public final String simpleName;
     public final int dimensions;
@@ -46,13 +43,14 @@
         assert name.length() > 0 : "name cannot be empty";
 
         int dims = 0;
+        int startIndex = 0;
+        while (name.charAt(startIndex) == '[') {
+            startIndex++;
+            dims++;
+        }
+
         // Decode name if necessary.
         if (name.charAt(name.length() - 1) == ';') {
-            int startIndex = 0;
-            while (name.charAt(startIndex) == '[') {
-                startIndex++;
-                dims++;
-            }
             assert name.charAt(startIndex) == 'L';
             this.simpleName = name.substring(startIndex + 1, name.length() - 1);
             this.name = name;
@@ -116,4 +114,9 @@
     public CiKind getRepresentationKind(RiType.Representation r) {
         return CiKind.Object;
     }
+
+    @Override
+    public RiResolvedType resolve(RiResolvedType accessingClass) {
+        return (RiResolvedType) compiler.lookupType(name, (HotSpotTypeResolved) accessingClass, true);
+    }
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Wed Feb 08 21:15:00 2012 -0800
@@ -1173,7 +1173,7 @@
     private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) {
        @Override
        protected XirTemplate create(CiXirAssembler asm, long flags) {
-           asm.restart();
+           asm.restart(CiKind.Void);
            XirParameter objHub = asm.createInputParameter("objectHub", CiKind.Object);
            XirOperand hub = asm.createConstantInputParameter("hub", CiKind.Object);
            XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor);
@@ -1188,7 +1188,7 @@
            // if we get an exact match: continue.
            asm.jneq(falseSucc, objHub, checkHub);
 
-           return asm.finishTemplate(objHub, "typeCheck");
+           return asm.finishTemplate("typeCheck");
        }
     };
 
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java	Wed Feb 08 21:15:00 2012 -0800
@@ -28,10 +28,10 @@
 
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.target.amd64.*;
-import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.amd64.*;
+import com.oracle.max.graal.lir.asm.*;
 
 /**
  * Performs a hard-coded tail call to the specified target, which normally should be an RiCompiledCode instance.
@@ -72,6 +72,6 @@
         } else if (mode == OperandMode.Temp) {
             return EnumSet.of(OperandFlag.Register);
         }
-        throw Util.shouldNotReachHere();
+        throw GraalInternalError.shouldNotReachHere();
     }
 }
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/FrameStateBuilder.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/FrameStateBuilder.java	Wed Feb 08 21:15:00 2012 -0800
@@ -47,7 +47,7 @@
 
     private final RiResolvedMethod method;
 
-    public FrameStateBuilder(RiResolvedMethod method, int maxLocals, int maxStackSize, StructuredGraph graph) {
+    public FrameStateBuilder(RiResolvedMethod method, int maxLocals, int maxStackSize, StructuredGraph graph, boolean eagerResolve) {
         assert graph != null;
         this.method = method;
         this.graph = graph;
@@ -67,9 +67,12 @@
         }
         RiSignature sig = method.signature();
         int max = sig.argumentCount(false);
-        RiType accessingClass = method.holder();
+        RiResolvedType accessingClass = method.holder();
         for (int i = 0; i < max; i++) {
             RiType type = sig.argumentTypeAt(i, accessingClass);
+            if (eagerResolve) {
+                type = type.resolve(accessingClass);
+            }
             CiKind kind = type.kind(false).stackKind();
             Stamp stamp;
             if (kind == CiKind.Object && type instanceof RiResolvedType) {
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Wed Feb 08 21:15:00 2012 -0800
@@ -128,7 +128,7 @@
         methodSynchronizedObject = null;
         exceptionHandlers = null;
         this.currentGraph = graph;
-        this.frameState = new FrameStateBuilder(method, method.maxLocals(), method.maxStackSize(), graph);
+        this.frameState = new FrameStateBuilder(method, method.maxLocals(), method.maxStackSize(), graph, config.eagerResolving());
         build();
     }
 
@@ -500,7 +500,7 @@
                 break;
             }
             default:
-                throw Util.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
 
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64Arithmetic.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,559 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.amd64;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.asm.*;
+
+public enum AMD64Arithmetic {
+    IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
+    LADD, LSUB, LMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
+    FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR,
+    DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR,
+    INEG, LNEG,
+    I2L, L2I, I2B, I2C, I2S,
+    F2D, D2F,
+    I2F, I2D, F2I, D2I,
+    L2F, L2D, F2L, D2L,
+    MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L;
+
+
+    public static class Op1Reg extends AMD64LIRInstruction {
+        public Op1Reg(AMD64Arithmetic opcode, CiValue result, CiValue x) {
+            super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            CiValue result = output(0);
+            CiValue x = input(0);
+
+            emit(tasm, masm, (AMD64Arithmetic) code, result, x, null);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public static class Op1Stack extends AMD64LIRInstruction {
+        public Op1Stack(AMD64Arithmetic opcode, CiValue result, CiValue x) {
+            super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            CiValue result = output(0);
+            CiValue x = input(0);
+
+            AMD64Move.move(tasm, masm, result, x);
+            emit(tasm, masm, (AMD64Arithmetic) code, result);
+        }
+
+        @Override
+        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public static class Op2Stack extends AMD64LIRInstruction {
+        public Op2Stack(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) {
+            super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            CiValue result = output(0);
+            CiValue x = input(0);
+            CiValue y = alive(0);
+
+            AMD64Move.move(tasm, masm, result, x);
+            emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            } else if (mode == OperandMode.Alive && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        @Override
+        public void verify() {
+            CiValue result = output(0);
+            CiValue x = input(0);
+            CiValue y = alive(0);
+
+            super.verify();
+            assert differentRegisters(result, y) || sameRegister(x, y);
+            verifyKind((AMD64Arithmetic) code, result, x, y);
+        }
+    }
+
+    public static class Op2Reg extends AMD64LIRInstruction {
+        public Op2Reg(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) {
+            super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            CiValue result = output(0);
+            CiValue x = input(0);
+            CiValue y = alive(0);
+
+            AMD64Move.move(tasm, masm, result, x);
+            emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            } else if (mode == OperandMode.Alive && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        @Override
+        public void verify() {
+            CiValue result = output(0);
+            CiValue x = input(0);
+            CiValue y = alive(0);
+
+            super.verify();
+            assert differentRegisters(result, y) || sameRegister(x, y);
+            verifyKind((AMD64Arithmetic) code, result, x, y);
+        }
+    }
+
+    public static class Op2RegCommutative extends AMD64LIRInstruction {
+        public Op2RegCommutative(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) {
+            super(opcode, new CiValue[] {result}, null, new CiValue[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            CiValue result = output(0);
+            CiValue x = input(0);
+            CiValue y = input(1);
+
+            if (sameRegister(result, y)) {
+                emit(tasm, masm, (AMD64Arithmetic) code, result, x, null);
+            } else {
+                AMD64Move.move(tasm, masm, result, x);
+                emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
+            }
+        }
+
+        @Override
+        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            } else if (mode == OperandMode.Input && index == 1) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        @Override
+        protected void verify() {
+            CiValue result = output(0);
+            CiValue x = input(0);
+            CiValue y = input(1);
+
+            super.verify();
+            verifyKind((AMD64Arithmetic) code, result, x, y);
+        }
+    }
+
+    public static class ShiftOp extends AMD64LIRInstruction {
+        public ShiftOp(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) {
+            super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            CiValue result = output(0);
+            CiValue x = input(0);
+            CiValue y = alive(0);
+
+            AMD64Move.move(tasm, masm, result, x);
+            emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
+        }
+
+        @Override
+        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            } else if (mode == OperandMode.Alive && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        @Override
+        public void verify() {
+            CiValue result = output(0);
+            CiValue x = input(0);
+            CiValue y = alive(0);
+
+            super.verify();
+            assert isConstant(y) || asRegister(y) == AMD64.rcx;
+            assert differentRegisters(result, y) || sameRegister(x, y);
+            verifyKind((AMD64Arithmetic) code, result, x, x);
+            assert y.kind.stackKind() == CiKind.Int;
+        }
+    }
+
+    public static class DivOp extends AMD64LIRInstruction {
+        public DivOp(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y, LIRDebugInfo info) {
+            super(opcode, new CiValue[] {result}, info, new CiValue[] {x}, new CiValue[] {y}, new CiValue[] {asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind)});
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            CiValue result = output(0);
+            CiValue y = alive(0);
+
+            emit(tasm, masm, (AMD64Arithmetic) code, result, y, info);
+        }
+
+        @Override
+        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Alive && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Temp && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        @Override
+        protected void verify() {
+            CiValue result = output(0);
+            CiValue x = input(0);
+            CiValue y = alive(0);
+
+            super.verify();
+            // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx
+            assert asRegister(x) == AMD64.rax;
+            assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue());
+            assert (name().endsWith("DIV") && asRegister(result) == AMD64.rax) || (name().endsWith("REM") && asRegister(result) == AMD64.rdx);
+            verifyKind((AMD64Arithmetic) code, result, x, y);
+        }
+    }
+
+
+    @SuppressWarnings("unused")
+    protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, CiValue result) {
+        switch (opcode) {
+            case INEG: masm.negl(asIntReg(result)); break;
+            case LNEG: masm.negq(asLongReg(result)); break;
+            case L2I:  masm.andl(asIntReg(result), 0xFFFFFFFF); break;
+            case I2B:  masm.signExtendByte(asIntReg(result)); break;
+            case I2C:  masm.andl(asIntReg(result), 0xFFFF); break;
+            case I2S:  masm.signExtendShort(asIntReg(result)); break;
+            default:   throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, CiValue dst, CiValue src, LIRDebugInfo info) {
+        int exceptionOffset = -1;
+        if (isRegister(src)) {
+            switch (opcode) {
+                case IADD: masm.addl(asIntReg(dst),  asIntReg(src)); break;
+                case ISUB: masm.subl(asIntReg(dst),  asIntReg(src)); break;
+                case IAND: masm.andl(asIntReg(dst),  asIntReg(src)); break;
+                case IMUL: masm.imull(asIntReg(dst), asIntReg(src)); break;
+                case IOR:  masm.orl(asIntReg(dst),   asIntReg(src)); break;
+                case IXOR: masm.xorl(asIntReg(dst),  asIntReg(src)); break;
+                case ISHL: masm.shll(asIntReg(dst)); break;
+                case ISHR: masm.sarl(asIntReg(dst)); break;
+                case IUSHR:masm.shrl(asIntReg(dst)); break;
+
+                case LADD: masm.addq(asLongReg(dst),  asLongReg(src)); break;
+                case LSUB: masm.subq(asLongReg(dst),  asLongReg(src)); break;
+                case LMUL: masm.imulq(asLongReg(dst), asLongReg(src)); break;
+                case LAND: masm.andq(asLongReg(dst),  asLongReg(src)); break;
+                case LOR:  masm.orq(asLongReg(dst),   asLongReg(src)); break;
+                case LXOR: masm.xorq(asLongReg(dst),  asLongReg(src)); break;
+                case LSHL: masm.shlq(asLongReg(dst)); break;
+                case LSHR: masm.sarq(asLongReg(dst)); break;
+                case LUSHR:masm.shrq(asLongReg(dst)); break;
+
+                case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); break;
+                case FSUB: masm.subss(asFloatReg(dst), asFloatReg(src)); break;
+                case FMUL: masm.mulss(asFloatReg(dst), asFloatReg(src)); break;
+                case FDIV: masm.divss(asFloatReg(dst), asFloatReg(src)); break;
+                case FAND: masm.andps(asFloatReg(dst), asFloatReg(src)); break;
+                case FOR:  masm.orps(asFloatReg(dst),  asFloatReg(src)); break;
+                case FXOR: masm.xorps(asFloatReg(dst), asFloatReg(src)); break;
+
+                case DADD: masm.addsd(asDoubleReg(dst), asDoubleReg(src)); break;
+                case DSUB: masm.subsd(asDoubleReg(dst), asDoubleReg(src)); break;
+                case DMUL: masm.mulsd(asDoubleReg(dst), asDoubleReg(src)); break;
+                case DDIV: masm.divsd(asDoubleReg(dst), asDoubleReg(src)); break;
+                case DAND: masm.andpd(asDoubleReg(dst), asDoubleReg(src)); break;
+                case DOR:  masm.orpd(asDoubleReg(dst),  asDoubleReg(src)); break;
+                case DXOR: masm.xorpd(asDoubleReg(dst), asDoubleReg(src)); break;
+
+                case I2L: masm.movslq(asLongReg(dst), asIntReg(src)); break;
+                case F2D: masm.cvtss2sd(asDoubleReg(dst), asFloatReg(src)); break;
+                case D2F: masm.cvtsd2ss(asFloatReg(dst), asDoubleReg(src)); break;
+                case I2F: masm.cvtsi2ssl(asFloatReg(dst), asIntReg(src)); break;
+                case I2D: masm.cvtsi2sdl(asDoubleReg(dst), asIntReg(src)); break;
+                case L2F: masm.cvtsi2ssq(asFloatReg(dst), asLongReg(src)); break;
+                case L2D: masm.cvtsi2sdq(asDoubleReg(dst), asLongReg(src)); break;
+                case F2I:
+                    masm.cvttss2sil(asIntReg(dst), asFloatReg(src));
+                    emitConvertFixup(tasm, masm, dst, src);
+                    break;
+                case D2I:
+                    masm.cvttsd2sil(asIntReg(dst), asDoubleReg(src));
+                    emitConvertFixup(tasm, masm, dst, src);
+                    break;
+                case F2L:
+                    masm.cvttss2siq(asLongReg(dst), asFloatReg(src));
+                    emitConvertFixup(tasm, masm, dst, src);
+                    break;
+                case D2L:
+                    masm.cvttsd2siq(asLongReg(dst), asDoubleReg(src));
+                    emitConvertFixup(tasm, masm, dst, src);
+                    break;
+                case MOV_I2F: masm.movdl(asFloatReg(dst), asIntReg(src)); break;
+                case MOV_L2D: masm.movdq(asDoubleReg(dst), asLongReg(src)); break;
+                case MOV_F2I: masm.movdl(asIntReg(dst), asFloatReg(src)); break;
+                case MOV_D2L: masm.movdq(asLongReg(dst), asDoubleReg(src)); break;
+
+                case IDIV:
+                case IREM:
+                    masm.cdql();
+                    exceptionOffset = masm.codeBuffer.position();
+                    masm.idivl(asRegister(src));
+                    break;
+
+                case LDIV:
+                case LREM:
+                    Label continuation = new Label();
+                    if (opcode == LDIV) {
+                        // check for special case of Long.MIN_VALUE / -1
+                        Label normalCase = new Label();
+                        masm.movq(AMD64.rdx, java.lang.Long.MIN_VALUE);
+                        masm.cmpq(AMD64.rax, AMD64.rdx);
+                        masm.jcc(ConditionFlag.notEqual, normalCase);
+                        masm.cmpl(asRegister(src), -1);
+                        masm.jcc(ConditionFlag.equal, continuation);
+                        masm.bind(normalCase);
+                    }
+
+                    masm.cdqq();
+                    exceptionOffset = masm.codeBuffer.position();
+                    masm.idivq(asRegister(src));
+                    masm.bind(continuation);
+                    break;
+
+                case IUDIV:
+                case IUREM:
+                    // Must zero the high 64-bit word (in RDX) of the dividend
+                    masm.xorq(AMD64.rdx, AMD64.rdx);
+                    exceptionOffset = masm.codeBuffer.position();
+                    masm.divl(asRegister(src));
+                    break;
+
+                case LUDIV:
+                case LUREM:
+                    // Must zero the high 64-bit word (in RDX) of the dividend
+                    masm.xorq(AMD64.rdx, AMD64.rdx);
+                    exceptionOffset = masm.codeBuffer.position();
+                    masm.divq(asRegister(src));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(src)) {
+            switch (opcode) {
+                case IADD: masm.incrementl(asIntReg(dst), tasm.asIntConst(src)); break;
+                case ISUB: masm.decrementl(asIntReg(dst), tasm.asIntConst(src)); break;
+                case IMUL: masm.imull(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break;
+                case IAND: masm.andl(asIntReg(dst), tasm.asIntConst(src)); break;
+                case IOR:  masm.orl(asIntReg(dst),  tasm.asIntConst(src)); break;
+                case IXOR: masm.xorl(asIntReg(dst), tasm.asIntConst(src)); break;
+                case ISHL: masm.shll(asIntReg(dst), tasm.asIntConst(src) & 31); break;
+                case ISHR: masm.sarl(asIntReg(dst), tasm.asIntConst(src) & 31); break;
+                case IUSHR:masm.shrl(asIntReg(dst), tasm.asIntConst(src) & 31); break;
+
+                case LADD: masm.addq(asLongReg(dst), tasm.asIntConst(src)); break;
+                case LSUB: masm.subq(asLongReg(dst), tasm.asIntConst(src)); break;
+                case LMUL: masm.imulq(asLongReg(dst), asLongReg(dst), tasm.asIntConst(src)); break;
+                case LAND: masm.andq(asLongReg(dst), tasm.asIntConst(src)); break;
+                case LOR:  masm.orq(asLongReg(dst),  tasm.asIntConst(src)); break;
+                case LXOR: masm.xorq(asLongReg(dst), tasm.asIntConst(src)); break;
+                case LSHL: masm.shlq(asLongReg(dst), tasm.asIntConst(src) & 63); break;
+                case LSHR: masm.sarq(asLongReg(dst), tasm.asIntConst(src) & 63); break;
+                case LUSHR:masm.shrq(asLongReg(dst), tasm.asIntConst(src) & 63); break;
+
+                case FADD: masm.addss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
+                case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
+                case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
+                case FAND: masm.andps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break;
+                case FOR:  masm.orps(asFloatReg(dst),  tasm.asFloatConstRef(src, 16)); break;
+                case FXOR: masm.xorps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break;
+                case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
+
+                case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
+                case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
+                case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
+                case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
+                case DAND: masm.andpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break;
+                case DOR:  masm.orpd(asDoubleReg(dst),  tasm.asDoubleConstRef(src, 16)); break;
+                case DXOR: masm.xorpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break;
+                default:   throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            switch (opcode) {
+                case IADD: masm.addl(asIntReg(dst), tasm.asIntAddr(src)); break;
+                case ISUB: masm.subl(asIntReg(dst), tasm.asIntAddr(src)); break;
+                case IAND: masm.andl(asIntReg(dst), tasm.asIntAddr(src)); break;
+                case IOR:  masm.orl(asIntReg(dst),  tasm.asIntAddr(src)); break;
+                case IXOR: masm.xorl(asIntReg(dst), tasm.asIntAddr(src)); break;
+
+                case LADD: masm.addq(asLongReg(dst), tasm.asLongAddr(src)); break;
+                case LSUB: masm.subq(asLongReg(dst), tasm.asLongAddr(src)); break;
+                case LAND: masm.andq(asLongReg(dst), tasm.asLongAddr(src)); break;
+                case LOR:  masm.orq(asLongReg(dst),  tasm.asLongAddr(src)); break;
+                case LXOR: masm.xorq(asLongReg(dst), tasm.asLongAddr(src)); break;
+
+                case FADD: masm.addss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
+                case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
+                case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
+                case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
+
+                case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
+                case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
+                case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
+                case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
+                default:   throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        if (info != null) {
+            assert exceptionOffset != -1;
+            tasm.recordImplicitException(exceptionOffset, info);
+        }
+    }
+
+    private static void emitConvertFixup(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x) {
+        ConvertSlowPath slowPath = new ConvertSlowPath(result, x);
+        tasm.slowPaths.add(slowPath);
+        switch (result.kind) {
+            case Int:  masm.cmpl(asIntReg(result),  Integer.MIN_VALUE); break;
+            case Long: masm.cmpq(asLongReg(result), tasm.asLongConstRef(CiConstant.forLong(java.lang.Long.MIN_VALUE))); break;
+            default:   throw GraalInternalError.shouldNotReachHere();
+        }
+        masm.jcc(ConditionFlag.equal, slowPath.start);
+        masm.bind(slowPath.continuation);
+    }
+
+    private static class ConvertSlowPath extends AMD64SlowPath {
+        public final Label start = new Label();
+        public final Label continuation = new Label();
+        private final CiValue result;
+        private final CiValue x;
+
+        public ConvertSlowPath(CiValue result, CiValue x) {
+            this.result = result;
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            masm.bind(start);
+            switch (x.kind) {
+                case Float:  masm.ucomiss(asFloatReg(x),  tasm.asFloatConstRef(CiConstant.FLOAT_0)); break;
+                case Double: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(CiConstant.DOUBLE_0)); break;
+                default:     throw GraalInternalError.shouldNotReachHere();
+            }
+            Label nan = new Label();
+            masm.jcc(ConditionFlag.parity, nan);
+            masm.jcc(ConditionFlag.below, continuation);
+
+            // input is > 0 -> return maxInt
+            // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff
+            switch (result.kind) {
+                case Int:  masm.decrementl(asIntReg(result),  1); break;
+                case Long: masm.decrementq(asLongReg(result), 1); break;
+                default:   throw GraalInternalError.shouldNotReachHere();
+            }
+            masm.jmp(continuation);
+
+            // input is NaN -> return 0
+            masm.bind(nan);
+            masm.xorptr(asRegister(result), asRegister(result));
+            masm.jmp(continuation);
+        }
+    }
+
+
+    private static void verifyKind(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) {
+        assert (opcode.name().startsWith("I") && result.kind == CiKind.Int && x.kind.stackKind() == CiKind.Int && y.kind.stackKind() == CiKind.Int)
+            || (opcode.name().startsWith("L") && result.kind == CiKind.Long && x.kind == CiKind.Long && y.kind == CiKind.Long)
+            || (opcode.name().startsWith("F") && result.kind == CiKind.Float && x.kind == CiKind.Float && y.kind == CiKind.Float)
+            || (opcode.name().startsWith("D") && result.kind == CiKind.Double && x.kind == CiKind.Double && y.kind == CiKind.Double);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64Call.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.amd64;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ci.CiTargetMethod.Mark;
+import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.asm.*;
+
+public class AMD64Call {
+
+    public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+        private final Object targetMethod;
+        private final Map<XirMark, Mark> marks;
+
+        public DirectCallOp(Object targetMethod, CiValue result, CiValue[] parameters, LIRDebugInfo info, Map<XirMark, Mark> marks) {
+            super("CALL_DIRECT", new CiValue[] {result}, info, parameters, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.targetMethod = targetMethod;
+            this.marks = marks;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            callAlignment(tasm, masm);
+            if (marks != null) {
+                marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0]));
+            }
+            directCall(tasm, masm, targetMethod, info);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+            } else if (mode == OperandMode.Output) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public static class IndirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+        private final Object targetMethod;
+        private final Map<XirMark, Mark> marks;
+
+        private static CiValue[] concat(CiValue[] parameters, CiValue targetAddress) {
+            CiValue[] result = Arrays.copyOf(parameters, parameters.length + 1);
+            result[result.length - 1] = targetAddress;
+            return result;
+        }
+
+        public IndirectCallOp(Object targetMethod, CiValue result, CiValue[] parameters, CiValue targetAddress, LIRDebugInfo info, Map<XirMark, Mark> marks) {
+            super("CALL_INDIRECT", new CiValue[] {result}, info, concat(parameters, targetAddress), LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.targetMethod = targetMethod;
+            this.marks = marks;
+        }
+
+        private CiValue targetAddress() {
+            return input(inputs.length - 1);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            callAlignment(tasm, masm);
+            if (marks != null) {
+                marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0]));
+            }
+            indirectCall(tasm, masm, asRegister(targetAddress()), targetMethod, info);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+            } else if (mode == OperandMode.Output) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static void callAlignment(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        // make sure that the displacement word of the call ends up word aligned
+        int offset = masm.codeBuffer.position();
+        offset += tasm.target.arch.machineCodeCallDisplacementOffset;
+        while (offset++ % tasm.target.wordSize != 0) {
+            masm.nop();
+        }
+    }
+
+    public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRDebugInfo info) {
+        int before = masm.codeBuffer.position();
+        if (target instanceof CiRuntimeCall) {
+            long maxOffset = tasm.runtime.getMaxCallTargetOffset((CiRuntimeCall) target);
+            if (maxOffset != (int) maxOffset) {
+                // offset might not fit a 32-bit immediate, generate an
+                // indirect call with a 64-bit immediate
+                CiRegister scratch = tasm.frameMap.registerConfig.getScratchRegister();
+                // TODO(cwi): we want to get rid of a generally reserved scratch register.
+                masm.movq(scratch, 0L);
+                masm.call(scratch);
+            } else {
+                masm.call();
+            }
+        } else {
+            masm.call();
+        }
+        int after = masm.codeBuffer.position();
+        tasm.recordDirectCall(before, after, tasm.runtime.asCallTarget(target), info);
+        tasm.recordExceptionHandlers(after, info);
+        masm.ensureUniquePC();
+    }
+
+    public static void directJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target) {
+        int before = masm.codeBuffer.position();
+        masm.jmp(0, true);
+        int after = masm.codeBuffer.position();
+        tasm.recordDirectCall(before, after, tasm.runtime.asCallTarget(target), null);
+        masm.ensureUniquePC();
+    }
+
+    public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiRegister dst, Object target, LIRDebugInfo info) {
+        int before = masm.codeBuffer.position();
+        masm.call(dst);
+        int after = masm.codeBuffer.position();
+        tasm.recordIndirectCall(before, after, tasm.runtime.asCallTarget(target), info);
+        tasm.recordExceptionHandlers(after, info);
+        masm.ensureUniquePC();
+    }
+
+    public static void shouldNotReachHere(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        boolean assertions = false;
+        assert (assertions = true) == true;
+
+        if (assertions) {
+            directCall(tasm, masm, CiRuntimeCall.Debug, null);
+            masm.hlt();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64Compare.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.amd64;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.asm.*;
+
+public enum AMD64Compare {
+    ICMP, LCMP, ACMP, FCMP, DCMP;
+
+    public static class CompareOp extends AMD64LIRInstruction {
+        public CompareOp(AMD64Compare opcode, CiValue x, CiValue y) {
+            super(opcode, LIRInstruction.NO_OPERANDS, null, new CiValue[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            CiValue x = input(0);
+            CiValue y = input(1);
+            emit(tasm, masm, (AMD64Compare) code, x, y);
+        }
+
+        @Override
+        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Input && index == 1) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        @Override
+        protected void verify() {
+            CiValue x = input(0);
+            CiValue y = input(1);
+
+            super.verify();
+            assert (name().startsWith("I") && x.kind == CiKind.Int && y.kind.stackKind() == CiKind.Int)
+                || (name().startsWith("I") && x.kind == CiKind.Jsr && y.kind == CiKind.Jsr)
+                || (name().startsWith("L") && x.kind == CiKind.Long && y.kind == CiKind.Long)
+                || (name().startsWith("A") && x.kind == CiKind.Object && y.kind == CiKind.Object)
+                || (name().startsWith("F") && x.kind == CiKind.Float && y.kind == CiKind.Float)
+                || (name().startsWith("D") && x.kind == CiKind.Double && y.kind == CiKind.Double);
+        }
+    }
+
+    public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Compare opcode, CiValue x, CiValue y) {
+        if (isRegister(y)) {
+            switch (opcode) {
+                case ICMP: masm.cmpl(asIntReg(x), asIntReg(y)); break;
+                case LCMP: masm.cmpq(asLongReg(x), asLongReg(y)); break;
+                case ACMP: masm.cmpptr(asObjectReg(x), asObjectReg(y)); break;
+                case FCMP: masm.ucomiss(asFloatReg(x), asFloatReg(y)); break;
+                case DCMP: masm.ucomisd(asDoubleReg(x), asDoubleReg(y)); break;
+                default:   throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(y)) {
+            switch (opcode) {
+                case ICMP: masm.cmpl(asIntReg(x), tasm.asIntConst(y)); break;
+                case LCMP: masm.cmpq(asLongReg(x), tasm.asIntConst(y)); break;
+                case ACMP:
+                    if (((CiConstant) y).isNull()) {
+                        masm.cmpq(asObjectReg(x), 0); break;
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons");
+                    }
+                case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(y)); break;
+                case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(y)); break;
+                default:   throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            switch (opcode) {
+                case ICMP: masm.cmpl(asIntReg(x), tasm.asIntAddr(y)); break;
+                case LCMP: masm.cmpq(asLongReg(x), tasm.asLongAddr(y)); break;
+                case ACMP: masm.cmpptr(asObjectReg(x), tasm.asObjectAddr(y)); break;
+                case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatAddr(y)); break;
+                case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleAddr(y)); break;
+                default:  throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64CompareToIntOpcode.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.amd64;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.asm.*;
+
+/**
+ * Implementation of the Java bytecodes that compare a long, float, or double value and produce the
+ * integer constants -1, 0, 1 on less, equal, or greater, respectively.  For floating point compares,
+ * unordered can be either greater {@link #CMP2INT_UG} or less {@link #CMP2INT_UL}.
+ */
+public enum AMD64CompareToIntOpcode {
+    CMP2INT, CMP2INT_UG, CMP2INT_UL;
+
+    public LIRInstruction create(CiValue result) {
+        CiValue[] outputs = new CiValue[] {result};
+
+        return new AMD64LIRInstruction(this, outputs, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) {
+            @Override
+            public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+                emit(masm, output(0));
+            }
+
+            @Override
+            protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+                if (mode == OperandMode.Output && index == 0) {
+                    return EnumSet.of(OperandFlag.Register);
+                }
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        };
+    }
+
+    private void emit(AMD64MacroAssembler masm, CiValue result) {
+        CiRegister dest = asIntReg(result);
+        Label high = new Label();
+        Label low = new Label();
+        Label done = new Label();
+
+        // comparison is done by a separate LIR instruction before
+        switch (this) {
+            case CMP2INT:
+                masm.jcc(ConditionFlag.greater, high);
+                masm.jcc(ConditionFlag.less, low);
+                break;
+            case CMP2INT_UG:
+                masm.jcc(ConditionFlag.parity, high);
+                masm.jcc(ConditionFlag.above, high);
+                masm.jcc(ConditionFlag.below, low);
+                break;
+            case CMP2INT_UL:
+                masm.jcc(ConditionFlag.parity, low);
+                masm.jcc(ConditionFlag.above, high);
+                masm.jcc(ConditionFlag.below, low);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+
+        // equal -> 0
+        masm.xorptr(dest, dest);
+        masm.jmp(done);
+
+        // greater -> 1
+        masm.bind(high);
+        masm.xorptr(dest, dest);
+        masm.incrementl(dest, 1);
+        masm.jmp(done);
+
+        // less -> -1
+        masm.bind(low);
+        masm.xorptr(dest, dest);
+        masm.decrementl(dest, 1);
+
+        masm.bind(done);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64ControlFlow.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.amd64;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ci.CiAddress.Scale;
+import com.oracle.max.cri.ci.CiTargetMethod.JumpTable;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.asm.*;
+import com.oracle.max.graal.nodes.calc.*;
+
+public class AMD64ControlFlow {
+
+    public static class ReturnOp extends AMD64LIRInstruction {
+        public ReturnOp(CiValue input) {
+            super("RETURN", LIRInstruction.NO_OPERANDS, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            masm.ret(0);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp {
+        protected Condition condition;
+        protected LabelRef destination;
+
+        public BranchOp(Condition condition, LabelRef destination, LIRDebugInfo info) {
+            super("BRANCH", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.condition = condition;
+            this.destination = destination;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            masm.jcc(intCond(condition), destination.label());
+        }
+
+        @Override
+        public LabelRef destination() {
+            return destination;
+        }
+
+        @Override
+        public void negate(LabelRef newDestination) {
+            destination = newDestination;
+            condition = condition.negate();
+        }
+
+        @Override
+        public String operationString() {
+            return condition.operator + " [" + destination + "]";
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static class FloatBranchOp extends BranchOp {
+        protected boolean unorderedIsTrue;
+
+        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination, LIRDebugInfo info) {
+            super(condition, destination, info);
+            this.unorderedIsTrue = unorderedIsTrue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            floatJcc(masm, condition, unorderedIsTrue, destination.label());
+        }
+
+        @Override
+        public void negate(LabelRef newDestination) {
+            super.negate(newDestination);
+            unorderedIsTrue = !unorderedIsTrue;
+        }
+
+        @Override
+        public String operationString() {
+            return condition.operator + " [" + destination + "]" + (unorderedIsTrue ? " unorderedIsTrue" : " unorderedIsFalse");
+        }
+    }
+
+
+    public static class TableSwitchOp extends AMD64LIRInstruction {
+        private final int lowKey;
+        private final LabelRef defaultTarget;
+        private final LabelRef[] targets;
+
+        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) {
+            super("TABLE_SWITCH", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, new CiValue[] {index}, new CiValue[] {scratch});
+            this.lowKey = lowKey;
+            this.defaultTarget = defaultTarget;
+            this.targets = targets;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(alive(0)), asLongReg(temp(0)));
+        }
+
+        @Override
+        public String operationString() {
+            StringBuilder buf = new StringBuilder(super.operationString());
+            buf.append("\ndefault: [").append(defaultTarget).append(']');
+            int key = lowKey;
+            for (LabelRef l : targets) {
+                buf.append("\ncase ").append(key).append(": [").append(l).append(']');
+                key++;
+            }
+            return buf.toString();
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Alive && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Temp && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static class CondMoveOp extends AMD64LIRInstruction {
+        private final Condition condition;
+
+        public CondMoveOp(Variable result, Condition condition, Variable trueValue, CiValue falseValue) {
+            super("CMOVE", new CiValue[] {result}, null, new CiValue[] {falseValue}, new CiValue[] {trueValue}, LIRInstruction.NO_OPERANDS);
+            this.condition = condition;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            cmove(tasm, masm, output(0), false, condition, false, alive(0), input(0));
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            } else if (mode == OperandMode.Alive && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        @Override
+        public String operationString() {
+            return condition.toString() + " " + super.operationString();
+        }
+    }
+
+
+    public static class FloatCondMoveOp extends AMD64LIRInstruction {
+        private final Condition condition;
+        private final boolean unorderedIsTrue;
+
+        public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
+            super("FLOAT_CMOVE", new CiValue[] {result}, null, LIRInstruction.NO_OPERANDS, new CiValue[] {trueValue, falseValue}, LIRInstruction.NO_OPERANDS);
+            this.condition = condition;
+            this.unorderedIsTrue = unorderedIsTrue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            cmove(tasm, masm, output(0), true, condition, unorderedIsTrue, alive(0), alive(1));
+        }
+
+        @Override
+        public String operationString() {
+            return condition.toString() + " unordered=" + unorderedIsTrue + " " + super.operationString();
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Alive && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Alive && index == 1) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    private static void tableswitch(TargetMethodAssembler tasm, AMD64MacroAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, CiRegister value, CiRegister scratch) {
+        Buffer buf = masm.codeBuffer;
+        // Compare index against jump table bounds
+        int highKey = lowKey + targets.length - 1;
+        if (lowKey != 0) {
+            // subtract the low value from the switch value
+            masm.subl(value, lowKey);
+            masm.cmpl(value, highKey - lowKey);
+        } else {
+            masm.cmpl(value, highKey);
+        }
+
+        // Jump to default target if index is not within the jump table
+        masm.jcc(ConditionFlag.above, defaultTarget.label());
+
+        // Set scratch to address of jump table
+        int leaPos = buf.position();
+        masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), 0));
+        int afterLea = buf.position();
+
+        // Load jump table entry into scratch and jump to it
+        masm.movslq(value, new CiAddress(CiKind.Int, scratch.asValue(), value.asValue(), Scale.Times4, 0));
+        masm.addq(scratch, value);
+        masm.jmp(scratch);
+
+        // Inserting padding so that jump table address is 4-byte aligned
+        if ((buf.position() & 0x3) != 0) {
+            masm.nop(4 - (buf.position() & 0x3));
+        }
+
+        // Patch LEA instruction above now that we know the position of the jump table
+        int jumpTablePos = buf.position();
+        buf.setPosition(leaPos);
+        masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), jumpTablePos - afterLea));
+        buf.setPosition(jumpTablePos);
+
+        // Emit jump table entries
+        for (LabelRef target : targets) {
+            Label label = target.label();
+            int offsetToJumpTableBase = buf.position() - jumpTablePos;
+            if (label.isBound()) {
+                int imm32 = label.position() - jumpTablePos;
+                buf.emitInt(imm32);
+            } else {
+                label.addPatchAt(buf.position());
+
+                buf.emitByte(0); // psuedo-opcode for jump table entry
+                buf.emitShort(offsetToJumpTableBase);
+                buf.emitByte(0); // padding to make jump table entry 4 bytes wide
+            }
+        }
+
+        JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4);
+        tasm.targetMethod.addAnnotation(jt);
+    }
+
+    private static void floatJcc(AMD64MacroAssembler masm, Condition condition, boolean unorderedIsTrue, Label label) {
+        ConditionFlag cond = floatCond(condition);
+        Label endLabel = new Label();
+        if (unorderedIsTrue && !trueOnUnordered(cond)) {
+            masm.jcc(ConditionFlag.parity, label);
+        } else if (!unorderedIsTrue && trueOnUnordered(cond)) {
+            masm.jcc(ConditionFlag.parity, endLabel);
+        }
+        masm.jcc(cond, label);
+        masm.bind(endLabel);
+    }
+
+    private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, boolean isFloat, Condition condition, boolean unorderedIsTrue, CiValue trueValue, CiValue falseValue) {
+        ConditionFlag cond = isFloat ? floatCond(condition) : intCond(condition);
+        // check that we don't overwrite an input operand before it is used.
+        assert !result.equals(trueValue);
+
+        AMD64Move.move(tasm, masm, result, falseValue);
+        cmove(tasm, masm, result, cond, trueValue);
+
+        if (isFloat) {
+            if (unorderedIsTrue && !trueOnUnordered(cond)) {
+                cmove(tasm, masm, result, ConditionFlag.parity, trueValue);
+            } else if (!unorderedIsTrue && trueOnUnordered(cond)) {
+                cmove(tasm, masm, result, ConditionFlag.parity, falseValue);
+            }
+        }
+    }
+
+    private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, ConditionFlag cond, CiValue other) {
+        if (isRegister(other)) {
+            assert asRegister(other) != asRegister(result) : "other already overwritten by previous move";
+            switch (other.kind) {
+                case Int:  masm.cmovl(cond, asRegister(result), asRegister(other)); break;
+                case Long: masm.cmovq(cond, asRegister(result), asRegister(other)); break;
+                default:   throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            switch (other.kind) {
+                case Int:  masm.cmovl(cond, asRegister(result), tasm.asAddress(other)); break;
+                case Long: masm.cmovq(cond, asRegister(result), tasm.asAddress(other)); break;
+                default:   throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    private static ConditionFlag intCond(Condition cond) {
+        switch (cond) {
+            case EQ: return ConditionFlag.equal;
+            case NE: return ConditionFlag.notEqual;
+            case LT: return ConditionFlag.less;
+            case LE: return ConditionFlag.lessEqual;
+            case GE: return ConditionFlag.greaterEqual;
+            case GT: return ConditionFlag.greater;
+            case BE: return ConditionFlag.belowEqual;
+            case AE: return ConditionFlag.aboveEqual;
+            case AT: return ConditionFlag.above;
+            case BT: return ConditionFlag.below;
+            case OF: return ConditionFlag.overflow;
+            case NOF: return ConditionFlag.noOverflow;
+            default: throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static ConditionFlag floatCond(Condition cond) {
+        switch (cond) {
+            case EQ: return ConditionFlag.equal;
+            case NE: return ConditionFlag.notEqual;
+            case BT: return ConditionFlag.below;
+            case BE: return ConditionFlag.belowEqual;
+            case AE: return ConditionFlag.aboveEqual;
+            case AT: return ConditionFlag.above;
+            default: throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static boolean trueOnUnordered(ConditionFlag condition) {
+        switch(condition) {
+            case aboveEqual:
+            case notEqual:
+            case above:
+            case less:
+            case overflow:
+                return false;
+            case equal:
+            case belowEqual:
+            case below:
+            case greaterEqual:
+            case noOverflow:
+                return true;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64LIRInstruction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.amd64;
+
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.asm.*;
+
+/**
+ * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method.
+ */
+public abstract class AMD64LIRInstruction extends LIRInstruction {
+
+    public AMD64LIRInstruction(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) {
+        super(opcode, outputs, info, inputs, alives, temps);
+    }
+
+    @Override
+    public final void emitCode(TargetMethodAssembler tasm) {
+        emitCode(tasm, (AMD64MacroAssembler) tasm.asm);
+    }
+
+    public abstract void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64Move.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.amd64;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+import static java.lang.Double.*;
+import static java.lang.Float.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.StandardOp.*;
+import com.oracle.max.graal.lir.asm.*;
+
+public class AMD64Move {
+
+    public static class SpillMoveOp extends AMD64LIRInstruction implements MoveOp {
+        public SpillMoveOp(CiValue result, CiValue input) {
+            super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            move(tasm, masm, getResult(), getInput());
+        }
+
+        @Override
+        public CiValue getInput() {
+            return input(0);
+        }
+        @Override
+        public CiValue getResult() {
+            return output(0);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp {
+        public MoveToRegOp(CiValue result, CiValue input) {
+            super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            move(tasm, masm, getResult(), getInput());
+        }
+
+        @Override
+        public CiValue getInput() {
+            return input(0);
+        }
+        @Override
+        public CiValue getResult() {
+            return output(0);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp {
+        public MoveFromRegOp(CiValue result, CiValue input) {
+            super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            move(tasm, masm, getResult(), getInput());
+        }
+
+        @Override
+        public CiValue getInput() {
+            return input(0);
+        }
+        @Override
+        public CiValue getResult() {
+            return output(0);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.RegisterHint);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static class LoadOp extends AMD64LIRInstruction {
+        public LoadOp(CiValue result, CiValue address, LIRDebugInfo info) {
+            super("LOAD", new CiValue[] {result}, info, new CiValue[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            load(tasm, masm, output(0), (CiAddress) input(0), info);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Address);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static class StoreOp extends AMD64LIRInstruction {
+        public StoreOp(CiValue address, CiValue input, LIRDebugInfo info) {
+            super("STORE", LIRInstruction.NO_OPERANDS, info, new CiValue[] {address, input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            store(tasm, masm, (CiAddress) input(0), input(1), info);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Address);
+            } else if (mode == OperandMode.Input && index == 1) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static class LeaOp extends AMD64LIRInstruction {
+        public LeaOp(CiValue result, CiValue address) {
+            super("LEA", new CiValue[] {result}, null, new CiValue[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            masm.leaq(asLongReg(output(0)), tasm.asAddress(input(0)));
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Address, OperandFlag.Stack, OperandFlag.Uninitialized);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static class MembarOp extends AMD64LIRInstruction {
+        private final int barriers;
+
+        public MembarOp(final int barriers) {
+            super("MEMBAR", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.barriers = barriers;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            masm.membar(barriers);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static class NullCheckOp extends AMD64LIRInstruction {
+        public NullCheckOp(Variable input, LIRDebugInfo info) {
+            super("NULL_CHECK", LIRInstruction.NO_OPERANDS, info, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            tasm.recordImplicitException(masm.codeBuffer.position(), info);
+            masm.nullCheck(asRegister(input(0)));
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static class CompareAndSwapOp extends AMD64LIRInstruction {
+        public CompareAndSwapOp(CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) {
+            super("CAS", new CiValue[] {result}, null, new CiValue[] {address, cmpValue, newValue}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            compareAndSwap(tasm, masm, output(0), asAddress(input(0)), input(1), input(2));
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Input && index == 0) {
+                return EnumSet.of(OperandFlag.Address);
+            } else if (mode == OperandMode.Input && index == 1) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Input && index == 2) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Output && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) {
+        if (isRegister(input)) {
+            if (isRegister(result)) {
+                reg2reg(masm, result, input);
+            } else if (isStackSlot(result)) {
+                reg2stack(tasm, masm, result, input);
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isStackSlot(input)) {
+            if (isRegister(result)) {
+                stack2reg(tasm, masm, result, input);
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(input)) {
+            if (isRegister(result)) {
+                const2reg(tasm, masm, result, (CiConstant) input);
+            } else if (isStackSlot(result)) {
+                const2stack(tasm, masm, result, (CiConstant) input);
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static void reg2reg(AMD64MacroAssembler masm, CiValue result, CiValue input) {
+        if (input.equals(result)) {
+            return;
+        }
+        switch (result.kind) {
+            case Jsr:
+            case Int:    masm.movl(asRegister(result),    asRegister(input)); break;
+            case Long:   masm.movq(asRegister(result),    asRegister(input)); break;
+            case Float:  masm.movflt(asFloatReg(result),  asFloatReg(input)); break;
+            case Double: masm.movdbl(asDoubleReg(result), asDoubleReg(input)); break;
+            case Object: masm.movq(asRegister(result),    asRegister(input)); break;
+            default:     throw GraalInternalError.shouldNotReachHere("kind=" + result.kind);
+        }
+    }
+
+    private static void reg2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) {
+        switch (result.kind) {
+            case Jsr:
+            case Int:    masm.movl(tasm.asAddress(result),   asRegister(input)); break;
+            case Long:   masm.movq(tasm.asAddress(result),   asRegister(input)); break;
+            case Float:  masm.movflt(tasm.asAddress(result), asFloatReg(input)); break;
+            case Double: masm.movsd(tasm.asAddress(result),  asDoubleReg(input)); break;
+            case Object: masm.movq(tasm.asAddress(result),   asRegister(input)); break;
+            default:     throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static void stack2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) {
+        switch (result.kind) {
+            case Jsr:
+            case Int:    masm.movl(asRegister(result),    tasm.asAddress(input)); break;
+            case Long:   masm.movq(asRegister(result),    tasm.asAddress(input)); break;
+            case Float:  masm.movflt(asFloatReg(result),  tasm.asAddress(input)); break;
+            case Double: masm.movdbl(asDoubleReg(result), tasm.asAddress(input)); break;
+            case Object: masm.movq(asRegister(result),    tasm.asAddress(input)); break;
+            default:     throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static void const2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) {
+        switch (result.kind) {
+            case Jsr:
+            case Int:
+                // Do not optimize with an XOR as this instruction may be between
+                // a CMP and a Jcc in which case the XOR will modify the condition
+                // flags and interfere with the Jcc.
+                masm.movl(asRegister(result), tasm.asIntConst(c));
+                break;
+            case Long:
+                // Do not optimize with an XOR as this instruction may be between
+                // a CMP and a Jcc in which case the XOR will modify the condition
+                // flags and interfere with the Jcc.
+                masm.movq(asRegister(result), c.asLong());
+                break;
+            case Float:
+                // This is *not* the same as 'constant == 0.0f' in the case where constant is -0.0f
+                if (Float.floatToRawIntBits(c.asFloat()) == Float.floatToRawIntBits(0.0f)) {
+                    masm.xorps(asFloatReg(result), asFloatReg(result));
+                } else {
+                    masm.movflt(asFloatReg(result), tasm.asFloatConstRef(c));
+                }
+                break;
+            case Double:
+                // This is *not* the same as 'constant == 0.0d' in the case where constant is -0.0d
+                if (Double.doubleToRawLongBits(c.asDouble()) == Double.doubleToRawLongBits(0.0d)) {
+                    masm.xorpd(asDoubleReg(result), asDoubleReg(result));
+                } else {
+                    masm.movdbl(asDoubleReg(result), tasm.asDoubleConstRef(c));
+                }
+                break;
+            case Object:
+                // Do not optimize with an XOR as this instruction may be between
+                // a CMP and a Jcc in which case the XOR will modify the condition
+                // flags and interfere with the Jcc.
+                if (c.isNull()) {
+                    masm.movq(asRegister(result), 0x0L);
+                } else if (tasm.target.inlineObjects) {
+                    tasm.recordDataReferenceInCode(c, 0);
+                    masm.movq(asRegister(result), 0xDEADDEADDEADDEADL);
+                } else {
+                    masm.movq(asRegister(result), tasm.recordDataReferenceInCode(c, 0));
+                }
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static void const2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) {
+        switch (result.kind) {
+            case Jsr:
+            case Int:    masm.movl(tasm.asAddress(result), c.asInt()); break;
+            case Long:   masm.movlong(tasm.asAddress(result), c.asLong()); break;
+            case Float:  masm.movl(tasm.asAddress(result), floatToRawIntBits(c.asFloat())); break;
+            case Double: masm.movlong(tasm.asAddress(result), doubleToRawLongBits(c.asDouble())); break;
+            case Object:
+                if (c.isNull()) {
+                    masm.movlong(tasm.asAddress(result), 0L);
+                } else {
+                    throw GraalInternalError.shouldNotReachHere("Non-null object constants must be in register");
+                }
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress loadAddr, LIRDebugInfo info) {
+        if (info != null) {
+            tasm.recordImplicitException(masm.codeBuffer.position(), info);
+        }
+        switch (loadAddr.kind) {
+            case Boolean:
+            case Byte:   masm.movsxb(asRegister(result),  loadAddr); break;
+            case Char:   masm.movzxl(asRegister(result),  loadAddr); break;
+            case Short:  masm.movswl(asRegister(result),  loadAddr); break;
+            case Int:    masm.movslq(asRegister(result),  loadAddr); break;
+            case Long:   masm.movq(asRegister(result),    loadAddr); break;
+            case Float:  masm.movflt(asFloatReg(result),  loadAddr); break;
+            case Double: masm.movdbl(asDoubleReg(result), loadAddr); break;
+            case Object: masm.movq(asRegister(result),    loadAddr); break;
+            default:     throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiAddress storeAddr, CiValue input, LIRDebugInfo info) {
+        if (info != null) {
+            tasm.recordImplicitException(masm.codeBuffer.position(), info);
+        }
+
+        if (isRegister(input)) {
+            switch (storeAddr.kind) {
+                case Boolean:
+                case Byte:   masm.movb(storeAddr,   asRegister(input)); break;
+                case Char:
+                case Short:  masm.movw(storeAddr,   asRegister(input)); break;
+                case Int:    masm.movl(storeAddr,   asRegister(input)); break;
+                case Long:   masm.movq(storeAddr,   asRegister(input)); break;
+                case Float:  masm.movflt(storeAddr, asFloatReg(input)); break;
+                case Double: masm.movsd(storeAddr,  asDoubleReg(input)); break;
+                case Object: masm.movq(storeAddr,   asRegister(input)); break;
+                default:     throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(input)) {
+            CiConstant c = (CiConstant) input;
+            switch (storeAddr.kind) {
+                case Boolean:
+                case Byte:   masm.movb(storeAddr, c.asInt() & 0xFF); break;
+                case Char:
+                case Short:  masm.movw(storeAddr, c.asInt() & 0xFFFF); break;
+                case Jsr:
+                case Int:    masm.movl(storeAddr, c.asInt()); break;
+                case Long:
+                    if (NumUtil.isInt(c.asLong())) {
+                        masm.movslq(storeAddr, (int) c.asLong());
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
+                    }
+                    break;
+                case Float:  masm.movl(storeAddr, floatToRawIntBits(c.asFloat())); break;
+                case Double: throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
+                case Object:
+                    if (c.isNull()) {
+                        masm.movptr(storeAddr, 0);
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
+                    }
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) {
+        assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax;
+
+        if (tasm.target.isMP) {
+            masm.lock();
+        }
+        switch (cmpValue.kind) {
+            case Int:    masm.cmpxchgl(asRegister(newValue), address); break;
+            case Long:
+            case Object: masm.cmpxchgq(asRegister(newValue), address); break;
+            default:     throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64SlowPath.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.amd64;
+
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.asm.*;
+
+/**
+ * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method.
+ */
+public abstract class AMD64SlowPath implements LIR.SlowPath {
+    @Override
+    public final void emitCode(TargetMethodAssembler tasm) {
+        emitCode(tasm, (AMD64MacroAssembler) tasm.asm);
+    }
+
+    public abstract void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/FrameMap.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ci.CiCallingConvention.Type;
+import com.oracle.max.cri.ri.*;
+
+/**
+ * This class is used to build the stack frame layout for a compiled method.
+ * A {@link CiStackSlot} is used to index slots of the frame relative to the stack pointer.
+ * The frame size is only fixed after register allocation when all spill slots have
+ * been allocated. Both the outgoing argument area and the spill are can grow until then.
+ * Therefore, outgoing arguments are indexed from the stack pointer, while spill slots
+ * are indexed from the beginning of the frame (and the total frame size has to be added
+ * to get the actual offset from the stack pointer).
+ * <br>
+ * This is the format of a stack frame:
+ * <pre>
+ *   Base       Contents
+ *
+ *            :                                :  -----
+ *   caller   | incoming overflow argument n   |    ^
+ *   frame    :     ...                        :    | positive
+ *            | incoming overflow argument 0   |    | offsets
+ *   ---------+--------------------------------+---------------------
+ *            | return address                 |    |            ^
+ *   current  +--------------------------------+    |            |    -----
+ *   frame    |                                |    |            |      ^
+ *            : callee save area               :    |            |      |
+ *            |                                |    |            |      |
+ *            +--------------------------------+    |            |      |
+ *            | spill slot 0                   |    | negative   |      |
+ *            :     ...                        :    v offsets    |      |
+ *            | spill slot n                   |  -----        total  frame
+ *            +--------------------------------+               frame  size
+ *            | alignment padding              |               size     |
+ *            +--------------------------------+  -----          |      |
+ *            | outgoing overflow argument n   |    ^            |      |
+ *            :     ...                        :    | positive   |      |
+ *            | outgoing overflow argument 0   |    | offsets    v      v
+ *    %sp-->  +--------------------------------+---------------------------
+ *
+ * </pre>
+ * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size
+ * of such a block may be greater than the size of a normal spill slot or the word size.
+ * <br>
+ * A runtime has two ways to reserve space in the stack frame for its own use: <ul>
+ * <li>A memory block somewhere in the frame of size {@link RiRuntime#getCustomStackAreaSize()}. The offset
+ *     to this block is returned in {@link CiTargetMethod#customStackAreaOffset()}.
+ * <li>At the beginning of the overflow argument area: The calling convention can specify that the first
+ *     overflow stack argument is not at offset 0, but at a specified offset o. Use
+ *     {@link RiRuntime#getMinimumOutgoingSize()} to make sure that call-free methods also have this space
+ *     reserved. Then the VM can use memory the memory at offset 0 relative to the stack pointer.
+ * </ul>
+ */
+public final class FrameMap {
+    public final RiRuntime runtime;
+    public final CiTarget target;
+    public final RiRegisterConfig registerConfig;
+
+    /**
+     * The final frame size, not including the size of the return address.
+     * The value is only set after register allocation is complete, i.e., after all spill slots have been allocated.
+     */
+    private int frameSize;
+
+    /**
+     * Size of the area occupied by spill slots and other stack-allocated memory blocks.
+     */
+    private int spillSize;
+
+    /**
+     * Size of the area occupied by outgoing overflow arguments.
+     * This value is adjusted as calling conventions for outgoing calls are retrieved.
+     */
+    private int outgoingSize;
+
+    /**
+     * The list of stack areas allocated in this frame that are present in every reference map.
+     */
+    private final List<CiStackSlot> objectStackBlocks;
+
+    /**
+     * The stack area reserved for use by the VM, or {@code null} if the VM does not request stack space.
+     */
+    private final CiStackSlot customArea;
+
+    /**
+     * Creates a new frame map for the specified method.
+     */
+    public FrameMap(RiRuntime runtime, CiTarget target, RiRegisterConfig registerConfig) {
+        this.runtime = runtime;
+        this.target = target;
+        this.registerConfig = registerConfig;
+        this.frameSize = -1;
+        this.spillSize = returnAddressSize() + calleeSaveAreaSize();
+        this.outgoingSize = runtime.getMinimumOutgoingSize();
+        this.objectStackBlocks = new ArrayList<>();
+        this.customArea = allocateStackBlock(runtime.getCustomStackAreaSize(), false);
+    }
+
+
+    private int returnAddressSize() {
+        return target.arch.returnAddressSize;
+    }
+
+    private int calleeSaveAreaSize() {
+        CiCalleeSaveLayout csl = registerConfig.getCalleeSaveLayout();
+        return csl != null ? csl.size : 0;
+    }
+
+    /**
+     * Gets the frame size of the compiled frame, not including the size of the return address.
+     * @return The size of the frame (in bytes).
+     */
+    public int frameSize() {
+        assert frameSize != -1 : "frame size not computed yet";
+        return frameSize;
+    }
+
+    /**
+     * Gets the total frame size of the compiled frame, including the size of the return address.
+     * @return The total size of the frame (in bytes).
+     */
+    public int totalFrameSize() {
+        return frameSize() + returnAddressSize();
+    }
+
+    /**
+     * Sets the frame size for this frame.
+     * @param frameSize The frame size (in bytes).
+     */
+    public void setFrameSize(int frameSize) {
+        assert this.frameSize == -1 : "must only be set once";
+        this.frameSize = frameSize;
+    }
+
+    /**
+     * Computes the frame size for this frame. After this method has been called, methods that change the
+     * frame size cannot be called anymore, e.g., no more spill slots or outgoing arguments can be requested.
+     */
+    public void finish() {
+        setFrameSize(target.alignFrameSize(outgoingSize + spillSize - returnAddressSize()));
+    }
+
+    /**
+     * Computes the offset of a stack slot relative to the frame register.
+     * This is also the bit index of stack slots in the reference map.
+     *
+     * @param slot a stack slot
+     * @return the offset of the stack slot
+     */
+    public int offsetForStackSlot(CiStackSlot slot) {
+        assert (!slot.rawAddFrameSize() && slot.rawOffset() < outgoingSize) ||
+            (slot.rawAddFrameSize() && slot.rawOffset() < 0 && -slot.rawOffset() <= spillSize) ||
+            (slot.rawAddFrameSize() && slot.rawOffset() >= 0);
+        return slot.offset(totalFrameSize());
+    }
+
+    /**
+     * Gets the offset to the stack area where callee-saved registers are stored.
+     * @return The offset to the callee save area (in bytes).
+     */
+    public int offsetToCalleeSaveArea() {
+        return frameSize() - calleeSaveAreaSize();
+    }
+
+    /**
+     * Gets the offset of the stack area stack block reserved for use by the VM, or -1 if the VM does not request stack space.
+     * @return The offset to the custom area (in bytes).
+     */
+    public int offsetToCustomArea() {
+        return customArea == null ? -1 : offsetForStackSlot(customArea);
+    }
+
+    /**
+     * Informs the frame map that the compiled code calls a particular method, which
+     * may need stack space for outgoing arguments.
+     * @param cc The calling convention for the called method.
+     * @param type The type of calling convention.
+     */
+    public void callsMethod(CiCallingConvention cc, Type type) {
+        // TODO look at the actual stack offsets?
+        assert type.out;
+        reserveOutgoing(cc.stackSize);
+    }
+
+    /**
+     * Reserves space for stack-based outgoing arguments.
+     * @param argsSize The amount of space (in bytes) to reserve for stack-based outgoing arguments.
+     */
+    public void reserveOutgoing(int argsSize) {
+        assert frameSize == -1 : "frame size must not yet be fixed";
+        outgoingSize = Math.max(outgoingSize, argsSize);
+    }
+
+    private CiStackSlot getSlot(CiKind kind, int additionalOffset) {
+        return CiStackSlot.get(kind, -spillSize + additionalOffset, true);
+    }
+
+    /**
+     * Reserves a spill slot in the frame of the method being compiled. The returned slot is aligned on its natural alignment,
+     * i.e., an 8-byte spill slot is aligned at an 8-byte boundary.
+     * @param kind The kind of the spill slot to be reserved.
+     * @return A spill slot denoting the reserved memory area.
+     */
+    public CiStackSlot allocateSpillSlot(CiKind kind) {
+        assert frameSize == -1 : "frame size must not yet be fixed";
+        int size = target.sizeInBytes(kind);
+        spillSize = NumUtil.roundUp(spillSize + size, size);
+        return getSlot(kind, 0);
+    }
+
+    /**
+     * Reserves a block of memory in the frame of the method being compiled. The returned block is aligned on a word boundary.
+     * If the requested size is 0, the method returns {@code null}.
+     *
+     * @param size The size to reserve (in bytes).
+     * @param refs Specifies if the block is all references. If true, the block will be in all reference maps for this method.
+     *             The caller is responsible to initialize the memory block before the first instruction that uses a reference map.
+     * @return A stack slot describing the begin of the memory block.
+     */
+    public CiStackSlot allocateStackBlock(int size, boolean refs) {
+        assert frameSize == -1 : "frame size must not yet be fixed";
+        if (size == 0) {
+            return null;
+        }
+        spillSize = NumUtil.roundUp(spillSize + size, target.wordSize);
+
+        if (refs) {
+            assert size % target.wordSize == 0;
+            CiStackSlot result = getSlot(CiKind.Object, 0);
+            objectStackBlocks.add(result);
+            for (int i = target.wordSize; i < size; i += target.wordSize) {
+                objectStackBlocks.add(getSlot(CiKind.Object, i));
+            }
+            return result;
+
+        } else {
+            return getSlot(target.wordKind, 0);
+        }
+    }
+
+
+    private int frameRefMapIndex(CiStackSlot slot) {
+        assert offsetForStackSlot(slot) % target.wordSize == 0;
+        return offsetForStackSlot(slot) / target.wordSize;
+    }
+
+    /**
+     * Initializes a reference map that covers all registers of the target architecture.
+     */
+    public CiBitMap initRegisterRefMap() {
+        return new CiBitMap(target.arch.registerReferenceMapBitCount);
+    }
+
+    /**
+     * Initializes a reference map. Initially, the size is large enough to cover all the
+     * slots in the frame. If the method has incoming reference arguments on the stack,
+     * the reference map might grow later when such a reference is set.
+     */
+    public CiBitMap initFrameRefMap() {
+        CiBitMap frameRefMap = new CiBitMap(frameSize() / target.wordSize);
+        for (CiStackSlot slot : objectStackBlocks) {
+            setReference(slot, null, frameRefMap);
+        }
+        return frameRefMap;
+    }
+
+    /**
+     * Marks the specified location as a reference in the reference map of the debug information.
+     * The tracked location can be a {@link CiRegisterValue} or a {@link CiStackSlot}. Note that a
+     * {@link CiConstant} is automatically tracked.
+     *
+     * @param location The location to be added to the reference map.
+     * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}.
+     * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}.
+     */
+    public void setReference(CiValue location, CiBitMap registerRefMap, CiBitMap frameRefMap) {
+        if (location.kind == CiKind.Object) {
+            if (isRegister(location)) {
+                assert registerRefMap.size() == target.arch.registerReferenceMapBitCount;
+                registerRefMap.set(asRegister(location).number);
+            } else if (isStackSlot(location)) {
+                int index = frameRefMapIndex(asStackSlot(location));
+                frameRefMap.grow(index + 1);
+                frameRefMap.set(index);
+            } else {
+                assert isConstant(location);
+            }
+        }
+    }
+
+    /**
+     * Clears the specified location as a reference in the reference map of the debug information.
+     * The tracked location can be a {@link CiRegisterValue} or a {@link CiStackSlot}. Note that a
+     * {@link CiConstant} is automatically tracked.
+     *
+     * @param location The location to be removed from the reference map.
+     * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}.
+     * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}.
+     */
+    public void clearReference(CiValue location, CiBitMap registerRefMap, CiBitMap frameRefMap) {
+        if (location.kind == CiKind.Object) {
+            if (location instanceof CiRegisterValue) {
+                assert registerRefMap.size() == target.arch.registerReferenceMapBitCount;
+                registerRefMap.clear(asRegister(location).number);
+            } else if (isStackSlot(location)) {
+                int index = frameRefMapIndex(asStackSlot(location));
+                if (index < frameRefMap.size()) {
+                    frameRefMap.clear(index);
+                }
+            } else {
+                assert isConstant(location);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIR.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.asm.*;
+import com.oracle.max.graal.lir.cfg.*;
+
+/**
+ * This class implements the overall container for the LIR graph
+ * and directs its construction, optimization, and finalization.
+ */
+public class LIR {
+
+    public final ControlFlowGraph cfg;
+
+    /**
+     * The nodes for the blocks.
+     * TODO: This should go away, we want all nodes connected with a next-pointer.
+     */
+    private final BlockMap<List<Node>> nodesFor;
+
+    /**
+     * The linear-scan ordered list of blocks.
+     */
+    private final List<Block> linearScanOrder;
+
+    /**
+     * The order in which the code is emitted.
+     */
+    private final List<Block> codeEmittingOrder;
+
+
+    public final List<SlowPath> slowPaths;
+
+    public final List<SlowPath> deoptimizationStubs;
+
+    /**
+     * The last slow path emitted, which can be used emit marker bytes.
+     */
+    public SlowPath methodEndMarker;
+
+    private int numVariables;
+
+    public SpillMoveFactory spillMoveFactory;
+
+    public interface SpillMoveFactory {
+        LIRInstruction createMove(CiValue result, CiValue input);
+        LIRInstruction createExchange(CiValue input1, CiValue input2);
+    }
+
+    public interface SlowPath {
+        void emitCode(TargetMethodAssembler tasm);
+    }
+
+    /**
+     * Creates a new LIR instance for the specified compilation.
+     * @param numLoops number of loops
+     * @param compilation the compilation
+     */
+    public LIR(ControlFlowGraph cfg, BlockMap<List<Node>> nodesFor, List<Block> linearScanOrder, List<Block> codeEmittingOrder) {
+        this.cfg = cfg;
+        this.nodesFor = nodesFor;
+        this.codeEmittingOrder = codeEmittingOrder;
+        this.linearScanOrder = linearScanOrder;
+
+        slowPaths = new ArrayList<>();
+        deoptimizationStubs = new ArrayList<>();
+    }
+
+    public List<Node> nodesFor(Block block) {
+        return nodesFor.get(block);
+    }
+
+    /**
+     * Gets the linear scan ordering of blocks as a list.
+     * @return the blocks in linear scan order
+     */
+    public List<Block> linearScanOrder() {
+        return linearScanOrder;
+    }
+
+    public List<Block> codeEmittingOrder() {
+        return codeEmittingOrder;
+    }
+
+    public int numVariables() {
+        return numVariables;
+    }
+
+    public int nextVariable() {
+        return numVariables++;
+    }
+
+    public void emitCode(TargetMethodAssembler tasm) {
+        for (Block b : codeEmittingOrder()) {
+            emitBlock(tasm, b);
+        }
+
+        // generate code for slow cases
+        for (SlowPath sp : slowPaths) {
+            emitSlowPath(tasm, sp);
+        }
+        // generate deoptimization stubs
+        for (SlowPath sp : deoptimizationStubs) {
+            emitSlowPath(tasm, sp);
+        }
+        // generate traps at the end of the method
+        emitSlowPath(tasm, methodEndMarker);
+    }
+
+    private static void emitBlock(TargetMethodAssembler tasm, Block block) {
+        if (Debug.isDumpEnabled()) {
+            tasm.blockComment(String.format("block B%d %s", block.getId(), block.getLoop()));
+        }
+
+        for (LIRInstruction op : block.lir) {
+            if (Debug.isDumpEnabled()) {
+                tasm.blockComment(String.format("%d %s", op.id(), op));
+            }
+
+            emitOp(tasm, op);
+        }
+    }
+
+    private static void emitOp(TargetMethodAssembler tasm, LIRInstruction op) {
+        try {
+            try {
+                op.emitCode(tasm);
+            } catch (AssertionError t) {
+                throw new GraalInternalError(t);
+            } catch (RuntimeException t) {
+                throw new GraalInternalError(t);
+            }
+        } catch (GraalInternalError e) {
+            throw e.addContext("lir instruction", op);
+        }
+    }
+
+    private static void emitSlowPath(TargetMethodAssembler tasm, SlowPath sp) {
+        if (Debug.isDumpEnabled()) {
+            tasm.blockComment(String.format("slow case %s", sp.getClass().getName()));
+        }
+        sp.emitCode(tasm);
+    }
+
+/*
+    private int lastDecodeStart;
+
+    private void printAssembly(TargetMethodAssembler tasm) {
+        byte[] currentBytes = tasm.asm.codeBuffer.copyData(lastDecodeStart, tasm.asm.codeBuffer.position());
+        if (currentBytes.length > 0) {
+            String disasm = tasm.runtime.disassemble(currentBytes, lastDecodeStart);
+            if (disasm.length() != 0) {
+                TTY.println(disasm);
+            } else {
+                TTY.println("Code [+%d]: %d bytes", lastDecodeStart, currentBytes.length);
+                Util.printBytes(lastDecodeStart, currentBytes, GraalOptions.PrintAssemblyBytesPerLine);
+            }
+        }
+        lastDecodeStart = tasm.asm.codeBuffer.position();
+    }
+
+
+    public static void printBlock(Block x) {
+        // print block id
+        TTY.print("B%d ", x.getId());
+
+        // print flags
+        if (x.isLoopHeader()) {
+            TTY.print("lh ");
+        }
+        if (x.isLoopEnd()) {
+            TTY.print("le ");
+        }
+
+        // print block bci range
+        TTY.print("[%d, %d] ", -1, -1);
+
+        // print predecessors and successors
+        if (x.numberOfPreds() > 0) {
+            TTY.print("preds: ");
+            for (int i = 0; i < x.numberOfPreds(); i++) {
+                TTY.print("B%d ", x.predAt(i).getId());
+            }
+        }
+
+        if (x.numberOfSux() > 0) {
+            TTY.print("sux: ");
+            for (int i = 0; i < x.numberOfSux(); i++) {
+                TTY.print("B%d ", x.suxAt(i).getId());
+            }
+        }
+
+        TTY.println();
+    }
+
+    public static void printLIR(List<Block> blocks) {
+        if (TTY.isSuppressed()) {
+            return;
+        }
+        TTY.println("LIR:");
+        int i;
+        for (i = 0; i < blocks.size(); i++) {
+            Block bb = blocks.get(i);
+            printBlock(bb);
+            TTY.println("__id_Instruction___________________________________________");
+            for (LIRInstruction op : bb.lir) {
+                TTY.println(op.toStringWithIdPrefix());
+                TTY.println();
+            }
+            TTY.println();
+        }
+    }
+*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIRDebugInfo.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.max.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.max.graal.lir.LIRInstruction.ValueProcedure;
+
+/**
+ * This class represents garbage collection and deoptimization information attached to a LIR instruction.
+ */
+public class LIRDebugInfo {
+    public final CiFrame topFrame;
+    private final CiVirtualObject[] virtualObjects;
+    private final List<CiStackSlot> pointerSlots;
+    public final LabelRef exceptionEdge;
+    private CiDebugInfo debugInfo;
+
+    public LIRDebugInfo(CiFrame topFrame, CiVirtualObject[] virtualObjects, List<CiStackSlot> pointerSlots, LabelRef exceptionEdge) {
+        this.topFrame = topFrame;
+        this.virtualObjects = virtualObjects;
+        this.pointerSlots = pointerSlots;
+        this.exceptionEdge = exceptionEdge;
+    }
+
+    public boolean hasDebugInfo() {
+        return debugInfo != null;
+    }
+
+    public CiDebugInfo debugInfo() {
+        assert debugInfo != null : "debug info not allocated yet";
+        return debugInfo;
+    }
+
+    /**
+     * Iterates the frame state and calls the {@link ValueProcedure} for every variable.
+     *
+     * @param proc The procedure called for variables.
+     */
+    public void forEachState(ValueProcedure proc) {
+        for (CiFrame cur = topFrame; cur != null; cur = cur.caller()) {
+            processValues(cur.values, proc);
+        }
+        if (virtualObjects != null) {
+            for (CiVirtualObject obj : virtualObjects) {
+                processValues(obj.values(), proc);
+            }
+        }
+    }
+
+    /**
+     * We filter out constant and illegal values ourself before calling the procedure, so {@link OperandFlag#Constant} and {@link OperandFlag#Illegal} need not be set.
+     */
+    private static final EnumSet<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+
+    private void processValues(CiValue[] values, ValueProcedure proc) {
+        for (int i = 0; i < values.length; i++) {
+            CiValue value = values[i];
+            if (value instanceof CiMonitorValue) {
+                CiMonitorValue monitor = (CiMonitorValue) value;
+                if (processed(monitor.owner)) {
+                    monitor.owner = proc.doValue(monitor.owner, OperandMode.Alive, STATE_FLAGS);
+                }
+
+            } else if (processed(value)) {
+                values[i] = proc.doValue(value, OperandMode.Alive, STATE_FLAGS);
+            }
+        }
+    }
+
+    private boolean processed(CiValue value) {
+        if (isIllegal(value)) {
+            // Ignore dead local variables.
+            return false;
+        } else if (isConstant(value)) {
+            // Ignore constants, the register allocator does not need to see them.
+            return false;
+        } else if (isVirtualObject(value)) {
+            assert Arrays.asList(virtualObjects).contains(value);
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+
+    public void finish(CiBitMap registerRefMap, CiBitMap frameRefMap, FrameMap frameMap) {
+        debugInfo = new CiDebugInfo(topFrame, registerRefMap, frameRefMap);
+
+        // Add additional stack slots for outgoing method parameters.
+        if (pointerSlots != null) {
+            for (CiStackSlot v : pointerSlots) {
+                frameMap.setReference(v, registerRefMap, frameRefMap);
+            }
+        }
+    }
+
+
+    @Override
+    public String toString() {
+        return debugInfo != null ? debugInfo.toString() : topFrame.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIRInsertionBuffer.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.lir;
+
+import java.util.*;
+
+/**
+ * A buffer to enqueue updates to a list. This avoids frequent re-sizing of the list and copying of list elements
+ * when insertions are done at multiple positions of the list. Additionally, it ensures that the list is not modified
+ * while it is, e.g., iterated, and instead only modified once after the iteration is done.
+ * <br>
+ * The buffer uses internal data structures to store the enqueued updates. To avoid allocations, a buffer can be re-used.
+ * Call the methods in the following order:
+ * {@link #init()}, {@link #append()}, {@link #append()}, ..., {@link #finish()}, {@link #init()}, ...
+ * <br>
+ * Note: This class does not depend on LIRInstruction, so we could make it a generic utility class.
+ */
+public final class LIRInsertionBuffer {
+
+    /**
+     * The lir list where ops of this buffer should be inserted later (null when uninitialized).
+     */
+    private List<LIRInstruction> lir;
+
+    /**
+     * List of insertion points. index and count are stored alternately:
+     * indexAndCount[i * 2]: the index into lir list where "count" ops should be inserted
+     * indexAndCount[i * 2 + 1]: the number of ops to be inserted at index
+     */
+    private final List<Integer> indexAndCount;
+
+    /**
+     * The LIROps to be inserted.
+     */
+    private final List<LIRInstruction> ops;
+
+
+    public LIRInsertionBuffer() {
+        indexAndCount = new ArrayList<>(8);
+        ops = new ArrayList<>(8);
+    }
+
+    /**
+     * Initialize this buffer. This method must be called before using {@link #append()}.
+     */
+    public void init(List<LIRInstruction> newLir) {
+        assert !initialized() : "already initialized";
+        assert indexAndCount.size() == 0 && ops.size() == 0;
+        this.lir = newLir;
+    }
+
+    public boolean initialized() {
+        return lir != null;
+    }
+
+    public List<LIRInstruction> lirList() {
+        return lir;
+    }
+
+    /**
+     * Enqueue a new instruction that will be appended to the instruction list when {@link #finish()} is called.
+     * The new instruction is added <b>before</b> the existing instruction with the given index. This method can only be called
+     * with increasing values of index, e.g., once an instruction was appended with index 4, subsequent instructions can
+     * only be appended with index 4 or higher.
+     */
+    public void append(int index, LIRInstruction op) {
+        int i = numberOfInsertionPoints() - 1;
+        if (i < 0 || indexAt(i) < index) {
+            appendNew(index, 1);
+        } else {
+            assert indexAt(i) == index : "can append LIROps in ascending order only";
+            assert countAt(i) > 0 : "check";
+            setCountAt(i, countAt(i) + 1);
+        }
+        ops.add(op);
+
+        assert verify();
+    }
+
+    /**
+     * Append all enqueued instructions to the instruction list. After that, {@link init()} can be called again to re-use this buffer.
+     */
+    public void finish() {
+        if (ops.size() > 0) {
+            int n = lir.size();
+            // increase size of instructions list
+            for (int i = 0; i < ops.size(); i++) {
+                lir.add(null);
+            }
+            // insert ops from buffer into instructions list
+            int opIndex = ops.size() - 1;
+            int ipIndex = numberOfInsertionPoints() - 1;
+            int fromIndex = n - 1;
+            int toIndex = lir.size() - 1;
+            while (ipIndex >= 0) {
+                int index = indexAt(ipIndex);
+                // make room after insertion point
+                while (fromIndex >= index) {
+                    lir.set(toIndex--, lir.get(fromIndex--));
+                }
+                // insert ops from buffer
+                for (int i = countAt(ipIndex); i > 0; i--) {
+                    lir.set(toIndex--, ops.get(opIndex--));
+                }
+                ipIndex--;
+            }
+            indexAndCount.clear();
+            ops.clear();
+        }
+        lir = null;
+    }
+
+    private void appendNew(int index, int count) {
+        indexAndCount.add(index);
+        indexAndCount.add(count);
+    }
+
+    private void setCountAt(int i, int value) {
+        indexAndCount.set((i << 1) + 1, value);
+    }
+
+    private int numberOfInsertionPoints() {
+        assert indexAndCount.size() % 2 == 0 : "must have a count for each index";
+        return indexAndCount.size() >> 1;
+    }
+
+    private int indexAt(int i) {
+        return indexAndCount.get((i << 1));
+    }
+
+    private int countAt(int i) {
+        return indexAndCount.get((i << 1) + 1);
+    }
+
+    private boolean verify() {
+        int sum = 0;
+        int prevIdx = -1;
+
+        for (int i = 0; i < numberOfInsertionPoints(); i++) {
+            assert prevIdx < indexAt(i) : "index must be ordered ascending";
+            sum += countAt(i);
+        }
+        assert sum == ops.size() : "wrong total sum";
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIRInstruction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.asm.*;
+
+/**
+ * The {@code LIRInstruction} class definition.
+ */
+public abstract class LIRInstruction {
+
+    public static final CiValue[] NO_OPERANDS = {};
+
+    /**
+     * Iterator for iterating over a list of values. Subclasses must overwrite one of the doValue methods.
+     * Clients of the class must only call the doValue method that takes additional parameters.
+     */
+    public abstract static class ValueProcedure {
+        /**
+         * Iterator method to be overwritten. This version of the iterator does not take additional parameters
+         * to keep the signature short.
+         *
+         * @param value The value that is iterated.
+         * @return The new value to replace the value that was passed in.
+         */
+        protected CiValue doValue(CiValue value) {
+            throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten");
+        }
+
+        /**
+         * Iterator method to be overwritten. This version of the iterator gets additional parameters about the
+         * processed value.
+         *
+         * @param value The value that is iterated.
+         * @param mode The operand mode for the value.
+         * @param flags A set of flags for the value.
+         * @return The new value to replace the value that was passed in.
+         */
+        public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
+            return doValue(value);
+        }
+    }
+
+
+    /**
+     * Constants denoting how a LIR instruction uses an operand.
+     */
+    public enum OperandMode {
+        /**
+         * The value must have been defined before. It is alive before the instruction until the beginning of the
+         * instruction, but not necessarily throughout the instruction. A register assigned to it can also be assigend
+         * to a Temp or Output operand. The value can be used again after the instruction, so the instruction must not
+         * modify the register.
+         */
+        Input,
+
+        /**
+         * The value must have been defined before. It is alive before the instruction and throughout the instruction. A
+         * register assigned to it cannot be assigned to a Temp or Output operand. The value can be used again after the
+         * instruction, so the instruction must not modify the register.
+         */
+        Alive,
+
+        /**
+         * The value must not have been defined before, and must not be used after the instruction. The instruction can
+         * do whatever it wants with the register assigned to it (or not use it at all).
+         */
+        Temp,
+
+        /**
+         * The value must not have been defined before. The instruction has to assign a value to the register. The
+         * value can (and most likely will) be used after the instruction.
+         */
+        Output,
+    }
+
+    /**
+     * Flags for an operand.
+     */
+    public enum OperandFlag {
+        /**
+         * The value can be a {@link CiRegisterValue}.
+         */
+        Register,
+
+        /**
+         * The value can be a {@link CiStackSlot}.
+         */
+        Stack,
+
+        /**
+         * The value can be a {@link CiAddress}.
+         */
+        Address,
+
+        /**
+         * The value can be a {@link CiConstant}.
+         */
+        Constant,
+
+        /**
+         * The value can be {@link CiValue#IllegalValue}.
+         */
+        Illegal,
+
+        /**
+         * The register allocator should try to assign a certain register to improve code quality.
+         * Use {@link LIRInstruction#forEachRegisterHint} to access the register hints.
+         */
+        RegisterHint,
+
+        /**
+         * The value can be uninitialized, e.g., a stack slot that has not written to before. This is only
+         * used to avoid false positives in verification code.
+         */
+        Uninitialized,
+    }
+
+    /**
+     * For validity checking of the operand flags defined by instruction subclasses.
+     */
+    private static final EnumMap<OperandMode, EnumSet<OperandFlag>> ALLOWED_FLAGS;
+
+    static {
+        ALLOWED_FLAGS = new EnumMap<>(OperandMode.class);
+        ALLOWED_FLAGS.put(OperandMode.Input,  EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Address, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint, OperandFlag.Uninitialized));
+        ALLOWED_FLAGS.put(OperandMode.Alive,  EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Address, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint, OperandFlag.Uninitialized));
+        ALLOWED_FLAGS.put(OperandMode.Temp,   EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint));
+        ALLOWED_FLAGS.put(OperandMode.Output, EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Illegal, OperandFlag.RegisterHint));
+    }
+
+    /**
+     * The opcode of this instruction.
+     */
+    protected final Object code;
+
+    /**
+     * The output operands for this instruction (modified by the register allocator).
+     */
+    protected CiValue[] outputs;
+
+    /**
+     * The input operands for this instruction (modified by the register allocator).
+     */
+    protected CiValue[] inputs;
+
+    /**
+     * The alive operands for this instruction (modified by the register allocator).
+     */
+    protected CiValue[] alives;
+
+    /**
+     * The temp operands for this instruction (modified by the register allocator).
+     */
+    protected CiValue[] temps;
+
+    /**
+     * Used to emit debug information.
+     */
+    public final LIRDebugInfo info;
+
+    /**
+     * Instruction id for register allocation.
+     */
+    private int id;
+
+    /**
+     * Constructs a new LIR instruction that has input and temp operands.
+     *
+     * @param opcode the opcode of the new instruction
+     * @param outputs the operands that holds the operation results of this instruction.
+     * @param info the {@link LIRDebugInfo} info that is to be preserved for the instruction. This will be {@code null} when no debug info is required for the instruction.
+     * @param inputs the input operands for the instruction.
+     * @param temps the temp operands for the instruction.
+     */
+    public LIRInstruction(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) {
+        this.code = opcode;
+        this.outputs = outputs;
+        this.inputs = inputs;
+        this.alives = alives;
+        this.temps = temps;
+        this.info = info;
+        this.id = -1;
+    }
+
+    public abstract void emitCode(TargetMethodAssembler tasm);
+
+
+    public final int id() {
+        return id;
+    }
+
+    public final void setId(int id) {
+        this.id = id;
+    }
+
+    /**
+     * Gets an input operand of this instruction.
+     *
+     * @param index the index of the operand requested.
+     * @return the {@code index}'th input operand.
+     */
+    protected final CiValue input(int index) {
+        return inputs[index];
+    }
+
+    /**
+     * Gets an alive operand of this instruction.
+     *
+     * @param index the index of the operand requested.
+     * @return the {@code index}'th alive operand.
+     */
+    protected final CiValue alive(int index) {
+        return alives[index];
+    }
+
+    /**
+     * Gets a temp operand of this instruction.
+     *
+     * @param index the index of the operand requested.
+     * @return the {@code index}'th temp operand.
+     */
+    protected final CiValue temp(int index) {
+        return temps[index];
+    }
+
+    /**
+     * Gets the result operand for this instruction.
+     *
+     * @return return the result operand
+     */
+    protected final CiValue output(int index) {
+        return outputs[index];
+    }
+
+    /**
+     * Gets the instruction name.
+     */
+    public String name() {
+        return code.toString();
+    }
+
+    public boolean hasOperands() {
+        return inputs.length > 0 || alives.length > 0 || temps.length > 0 || outputs.length > 0 || info != null || hasCall();
+    }
+
+    private static final EnumSet<OperandFlag> ADDRESS_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
+
+    private void forEach(CiValue[] values, OperandMode mode, ValueProcedure proc) {
+        for (int i = 0; i < values.length; i++) {
+            assert ALLOWED_FLAGS.get(mode).containsAll(flagsFor(mode, i));
+
+            CiValue value = values[i];
+            if (isAddress(value)) {
+                assert flagsFor(mode, i).contains(OperandFlag.Address);
+                CiAddress address = asAddress(value);
+                address.base = proc.doValue(address.base, mode, ADDRESS_FLAGS);
+                address.index = proc.doValue(address.index, mode, ADDRESS_FLAGS);
+            } else {
+                values[i] = proc.doValue(values[i], mode, flagsFor(mode, i));
+            }
+        }
+    }
+
+    public final void forEachInput(ValueProcedure proc) {
+        forEach(inputs, OperandMode.Input, proc);
+    }
+
+    public final void forEachAlive(ValueProcedure proc) {
+        forEach(alives, OperandMode.Alive, proc);
+    }
+
+    public final void forEachTemp(ValueProcedure proc) {
+        forEach(temps, OperandMode.Temp, proc);
+    }
+
+    public final void forEachOutput(ValueProcedure proc) {
+        forEach(outputs, OperandMode.Output, proc);
+    }
+
+    public final void forEachState(ValueProcedure proc) {
+        if (info != null) {
+            info.forEachState(proc);
+
+            if (this instanceof LIRXirInstruction) {
+                LIRXirInstruction xir = (LIRXirInstruction) this;
+                if (xir.infoAfter != null) {
+                    xir.infoAfter.forEachState(proc);
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns true when this instruction is a call instruction that destroys all caller-saved registers.
+     */
+    public final boolean hasCall() {
+        return this instanceof StandardOp.CallOp;
+    }
+
+    /**
+     * Iterates all register hints for the specified value, i.e., all preferred candidates for the register to be
+     * assigned to the value.
+     * <br>
+     * Subclasses can override this method. The default implementation processes all Input operands as the hints for
+     * an Output operand, and all Output operands as the hints for an Input operand.
+     *
+     * @param value The value the hints are needed for.
+     * @param mode The operand mode of the value.
+     * @param proc The procedure invoked for all the hints. If the procedure returns a non-null value, the iteration is stopped
+     *             and the value is returned by this method, i.e., clients can stop the iteration once a suitable hint has been found.
+     * @return The non-null value returned by the procedure, or null.
+     */
+    public CiValue forEachRegisterHint(CiValue value, OperandMode mode, ValueProcedure proc) {
+        CiValue[] hints;
+        if (mode == OperandMode.Input) {
+            hints = outputs;
+        } else if (mode == OperandMode.Output) {
+            hints = inputs;
+        } else {
+            return null;
+        }
+
+        for (int i = 0; i < hints.length; i++) {
+            CiValue result = proc.doValue(hints[i], null, null);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Used by the register allocator to decide which kind of location can be assigned to the operand.
+     * @param mode The kind of operand.
+     * @param index The index of the operand.
+     * @return The flags for the operand.
+     */
+    // TODO this method will go away when we have named operands, the flags will be specified as annotations instead.
+    protected abstract EnumSet<OperandFlag> flagsFor(OperandMode mode, int index);
+
+    protected void verify() {
+    }
+
+
+    public final String toStringWithIdPrefix() {
+        if (id != -1) {
+            return String.format("%4d %s", id, toString());
+        }
+        return "     " + toString();
+    }
+
+    /**
+     * Gets the operation performed by this instruction in terms of its operands as a string.
+     */
+    public String operationString() {
+        StringBuilder buf = new StringBuilder();
+        String sep = "";
+        if (outputs.length > 1) {
+            buf.append("(");
+        }
+        for (CiValue output : outputs) {
+            buf.append(sep).append(output);
+            sep = ", ";
+        }
+        if (outputs.length > 1) {
+            buf.append(")");
+        }
+        if (outputs.length > 0) {
+            buf.append(" = ");
+        }
+
+        if (inputs.length + alives.length != 1) {
+            buf.append("(");
+        }
+        sep = "";
+        for (CiValue input : inputs) {
+            buf.append(sep).append(input);
+            sep = ", ";
+        }
+        for (CiValue input : alives) {
+            buf.append(sep).append(input).append(" ~");
+            sep = ", ";
+        }
+        if (inputs.length + alives.length != 1) {
+            buf.append(")");
+        }
+
+        if (temps.length > 0) {
+            buf.append(" [");
+        }
+        sep = "";
+        for (CiValue temp : temps) {
+            buf.append(sep).append(temp);
+            sep = ", ";
+        }
+        if (temps.length > 0) {
+            buf.append("]");
+        }
+        return buf.toString();
+    }
+
+    protected void appendDebugInfo(StringBuilder buf) {
+        if (info != null) {
+            buf.append(" [bci:");
+            String sep = "";
+            for (CiFrame cur = info.topFrame; cur != null; cur = cur.caller()) {
+                buf.append(sep).append(cur.bci);
+                sep = ",";
+            }
+            buf.append("]");
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder(name()).append(' ').append(operationString());
+        appendDebugInfo(buf);
+        return buf.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIRVerifier.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+import static com.oracle.max.graal.lir.ValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.criutils.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.LIRInstruction.*;
+import com.oracle.max.graal.lir.cfg.*;
+
+public final class LIRVerifier {
+    private final LIR lir;
+    private final FrameMap frameMap;
+
+    private final boolean beforeRegisterAllocation;
+
+    private final BitSet[] blockLiveOut;
+    private final Object[] variableDefinitions;
+
+    private BitSet liveOutFor(Block block) {
+        return blockLiveOut[block.getId()];
+    }
+    private void setLiveOutFor(Block block, BitSet liveOut) {
+        blockLiveOut[block.getId()] = liveOut;
+    }
+
+    private int maxRegisterNum() {
+        return frameMap.target.arch.registers.length;
+    }
+
+    private boolean isAllocatableRegister(CiValue value) {
+        return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable;
+    }
+
+    public static boolean verify(final LIRInstruction op) {
+        ValueProcedure allowedProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return allowed(op, value, mode, flags); } };
+
+        op.forEachInput(allowedProc);
+        op.forEachAlive(allowedProc);
+        op.forEachState(allowedProc);
+        op.forEachTemp(allowedProc);
+        op.forEachOutput(allowedProc);
+
+        op.verify();
+        return true;
+    }
+
+    public static boolean verify(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) {
+        LIRVerifier verifier = new LIRVerifier(beforeRegisterAllocation, lir, frameMap);
+        verifier.verify();
+        return true;
+    }
+
+
+    private LIRVerifier(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) {
+        this.beforeRegisterAllocation = beforeRegisterAllocation;
+        this.lir = lir;
+        this.frameMap = frameMap;
+        this.blockLiveOut = new BitSet[lir.linearScanOrder().size()];
+        this.variableDefinitions = new Object[lir.numVariables()];
+    }
+
+    private BitSet curVariablesLive;
+    private CiValue[] curRegistersLive;
+
+    private Block curBlock;
+    private Object curInstruction;
+    private BitSet curRegistersDefined;
+
+    private void verify() {
+        ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
+        ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } };
+
+        curRegistersDefined = new BitSet();
+        for (Block block : lir.linearScanOrder()) {
+            curBlock = block;
+            curVariablesLive = new BitSet();
+            curRegistersLive = new CiValue[maxRegisterNum()];
+
+            if (block.getDominator() != null) {
+                curVariablesLive.or(liveOutFor(block.getDominator()));
+            }
+
+            assert block.lir.get(0) instanceof StandardOp.LabelOp : "block must start with label";
+            if (block.numberOfPreds() > 1) {
+                assert block.lir.get(0) instanceof StandardOp.PhiLabelOp : "phi mapping required for multiple predecessors";
+                CiValue[] phiDefinitions = ((StandardOp.PhiLabelOp) block.lir.get(0)).getPhiDefinitions();
+                if (!beforeRegisterAllocation) {
+                    assert phiDefinitions.length == 0;
+                }
+                for (Block pred : block.getPredecessors()) {
+                    assert pred.numberOfSux() == 1;
+                    LIRInstruction last = pred.lir.get(pred.lir.size() - 1);
+                    assert last instanceof StandardOp.PhiJumpOp : "phi mapping required for multiple successors";
+                    CiValue[] phiUses = ((StandardOp.PhiJumpOp) last).getPhiInputs();
+                    if (!beforeRegisterAllocation) {
+                        assert phiUses.length == 0;
+                    }
+                }
+            }
+
+            if (block.numberOfSux() > 0) {
+                LIRInstruction last = block.lir.get(block.lir.size() - 1);
+                assert last instanceof StandardOp.JumpOp || last instanceof LIRXirInstruction : "block with successor must end with unconditional jump";
+            }
+
+            for (LIRInstruction op : block.lir) {
+                curInstruction = op;
+
+                op.forEachInput(useProc);
+                if (op.hasCall()) {
+                    for (CiRegister register : frameMap.registerConfig.getCallerSaveRegisters()) {
+                        curRegistersLive[register.number] = null;
+                    }
+                }
+                curRegistersDefined.clear();
+                op.forEachAlive(useProc);
+                op.forEachState(useProc);
+                op.forEachTemp(defProc);
+                op.forEachOutput(defProc);
+
+                curInstruction = null;
+            }
+
+            setLiveOutFor(block, curVariablesLive);
+        }
+    }
+
+    private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        allowed(curInstruction, value, mode, flags);
+
+        if (isVariable(value)) {
+            assert beforeRegisterAllocation;
+
+            int variableIdx = asVariable(value).index;
+            if (!curVariablesLive.get(variableIdx)) {
+                TTY.println("block %s  instruction %s", curBlock, curInstruction);
+                TTY.println("live variables: %s", curVariablesLive);
+                if (variableDefinitions[variableIdx] != null) {
+                    TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]);
+                }
+                TTY.println("ERROR: Use of variable %s that is not defined in dominator", value);
+                throw GraalInternalError.shouldNotReachHere();
+            }
+
+        } else if (isAllocatableRegister(value)) {
+            int regNum = asRegister(value).number;
+            if (mode == OperandMode.Alive) {
+                curRegistersDefined.set(regNum);
+            }
+
+            if (beforeRegisterAllocation && curRegistersLive[regNum] != value) {
+                TTY.println("block %s  instruction %s", curBlock, curInstruction);
+                TTY.println("live registers: %s", Arrays.toString(curRegistersLive));
+                TTY.println("ERROR: Use of fixed register %s that is not defined in this block", value);
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+        return value;
+    }
+
+    private CiValue def(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        allowed(curInstruction, value, mode, flags);
+
+        if (isVariable(value)) {
+            assert beforeRegisterAllocation;
+
+            int variableIdx = asVariable(value).index;
+            if (variableDefinitions[variableIdx] != null) {
+                TTY.println("block %s  instruction %s", curBlock, curInstruction);
+                TTY.println("live variables: %s", curVariablesLive);
+                TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]);
+                TTY.println("ERROR: Variable %s defined multiple times", value);
+                throw GraalInternalError.shouldNotReachHere();
+            }
+            assert curInstruction != null;
+            variableDefinitions[variableIdx] = curInstruction;
+            assert !curVariablesLive.get(variableIdx);
+            if (mode == OperandMode.Output) {
+                curVariablesLive.set(variableIdx);
+            }
+
+        } else if (isAllocatableRegister(value)) {
+            int regNum = asRegister(value).number;
+            if (curRegistersDefined.get(regNum)) {
+                TTY.println("block %s  instruction %s", curBlock, curInstruction);
+                TTY.println("ERROR: Same register defined twice in the same instruction: %s", value);
+                throw GraalInternalError.shouldNotReachHere();
+            }
+            curRegistersDefined.set(regNum);
+
+            if (beforeRegisterAllocation) {
+                if (mode == OperandMode.Output) {
+                    curRegistersLive[regNum] = value;
+                } else {
+                    curRegistersLive[regNum] = null;
+                }
+            }
+        }
+        return value;
+    }
+
+    private static CiValue allowed(Object op, CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        if ((isVariable(value)  && flags.contains(OperandFlag.Register)) ||
+            (isRegister(value)  && flags.contains(OperandFlag.Register)) ||
+            (isStackSlot(value) && flags.contains(OperandFlag.Stack)) ||
+            (isConstant(value)  && flags.contains(OperandFlag.Constant) && mode != OperandMode.Output) ||
+            (isIllegal(value)   && flags.contains(OperandFlag.Illegal))) {
+            return value;
+        }
+        TTY.println("instruction %s", op);
+        TTY.println("mode: %s  flags: %s", mode, flags);
+        TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value);
+        throw GraalInternalError.shouldNotReachHere();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIRXirInstruction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.xir.*;
+import com.oracle.max.graal.graph.*;
+
+public abstract class LIRXirInstruction extends LIRInstruction {
+
+    public final CiValue[] originalOperands;
+    public final int outputOperandIndex;
+    public final int[] inputOperandIndices;
+    public final int[] tempOperandIndices;
+    public final XirSnippet snippet;
+    public final LIRDebugInfo infoAfter;
+    public final LabelRef trueSuccessor;
+    public final LabelRef falseSuccessor;
+
+    public LIRXirInstruction(Object opcode,
+                             XirSnippet snippet,
+                             CiValue[] originalOperands,
+                             CiValue outputOperand,
+                             CiValue[] inputs, CiValue[] temps,
+                             int[] inputOperandIndices, int[] tempOperandIndices,
+                             int outputOperandIndex,
+                             LIRDebugInfo info,
+                             LIRDebugInfo infoAfter,
+                             LabelRef trueSuccessor,
+                             LabelRef falseSuccessor) {
+        // Note that we register the XIR input operands as Alive, because the XIR specification allows that input operands
+        // are used at any time, even when the temp operands and the actual output operands have already be assigned.
+        super(opcode, isLegal(outputOperand) ? new CiValue[] {outputOperand} : LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, inputs, temps);
+        this.infoAfter = infoAfter;
+        this.snippet = snippet;
+        this.inputOperandIndices = inputOperandIndices;
+        this.tempOperandIndices = tempOperandIndices;
+        this.outputOperandIndex = outputOperandIndex;
+        this.originalOperands = originalOperands;
+        this.falseSuccessor = falseSuccessor;
+        this.trueSuccessor = trueSuccessor;
+        assert isLegal(outputOperand) || outputOperandIndex == -1;
+    }
+
+    @Override
+    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+        if (mode == OperandMode.Alive || mode == OperandMode.Temp) {
+            return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Illegal);
+        } else if (mode == OperandMode.Output && index == 0) {
+            return EnumSet.of(OperandFlag.Register);
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    public CiValue[] getOperands() {
+        for (int i = 0; i < inputOperandIndices.length; i++) {
+            originalOperands[inputOperandIndices[i]] = alive(i);
+        }
+        for (int i = 0; i < tempOperandIndices.length; i++) {
+            originalOperands[tempOperandIndices[i]] = temp(i);
+        }
+        if (outputOperandIndex != -1) {
+            originalOperands[outputOperandIndex] = output(0);
+        }
+        return originalOperands;
+    }
+
+    @Override
+    public String name() {
+        return "XIR: " + snippet.template;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LabelRef.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.lir;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.graal.lir.cfg.*;
+
+/**
+ * LIR instructions such as JUMP and BRANCH need to reference their target {@link Block}. However,
+ * direct references are not possible since the control flow graph (and therefore successors lists) can
+ * be changed by optimizations - and fixing the instructions is error prone.
+ * Therefore, we only reference of block B from block A only via the tuple (A, successor-index-of-B), i.e.,
+ * indirectly by storing the index into the successor list of A.
+ * Note that therefore it is not allowed to reorder the successor list!
+ *
+ * Labels of out-of-line stubs can be referenced directly, therefore it is also possible to construct a
+ * LabelRef for a Label directly via {@link #forLabel}.
+ */
+public abstract class LabelRef {
+
+    public abstract Label label();
+
+    /**
+     * Returns a new reference to a statically defined label.
+     * @param label The label that is always returned.
+     * @return The newly created label reference.
+     */
+    public static LabelRef forLabel(final Label label) {
+       return new LabelRef() {
+           @Override
+           public Label label() {
+               return label;
+           }
+
+           @Override
+           public String toString() {
+               return label.toString();
+           }
+       };
+    }
+
+    /**
+     * Returns a new reference to a successor of the given block.
+     * This allows to reference the given successor even when the successor list
+     * is modified between the creation of the reference and the call to {@link #getLabel}.
+     * @param block The base block that contains the successor list.
+     * @param suxIndex The index of the successor.
+     * @return The newly created label reference.
+     */
+    public static LabelRef forSuccessor(final Block block, final int suxIndex) {
+        return new LabelRef() {
+            @Override
+            public Label label() {
+                return ((StandardOp.LabelOp) block.suxAt(suxIndex).lir.get(0)).getLabel();
+            }
+
+            @Override
+            public String toString() {
+                return suxIndex < block.numberOfSux() ? block.suxAt(suxIndex).toString() : "?" + block + ":" + suxIndex + "?";
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/StandardOp.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.asm.*;
+
+/**
+ * A collection of machine-independent LIR operations, as well as interfaces to be implemented for specific kinds or LIR
+ * operations.
+ */
+public class StandardOp {
+
+    private static CiValue[] EMPTY = new CiValue[0];
+
+    /**
+     * LIR operation that defines the position of a label.
+     * The first operation of every block must implement this interface.
+     */
+    public static class LabelOp extends LIRInstruction {
+        private final Label label;
+        private final boolean align;
+
+        protected LabelOp(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps, Label label, boolean align) {
+            super(opcode, outputs, info, inputs, alives, temps);
+            this.label = label;
+            this.align = align;
+        }
+
+        public LabelOp(Label label, boolean align) {
+            this("LABEL", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, label, align);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm) {
+            if (align) {
+                tasm.asm.align(tasm.target.wordSize);
+            }
+            tasm.asm.bind(label);
+        }
+
+        @Override
+        public String operationString() {
+            return label.toString() + " " + super.operationString();
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        public Label getLabel() {
+            return label;
+        }
+    }
+
+    public static class PhiLabelOp extends LabelOp {
+        public PhiLabelOp(Label label, boolean align, CiValue[] phiDefinitions) {
+            super("PHI_LABEL", phiDefinitions, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, label, align);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Output) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        public void markResolved() {
+            outputs = EMPTY;
+        }
+
+        public CiValue[] getPhiDefinitions() {
+            return outputs;
+        }
+    }
+
+    /**
+     * LIR operation that is an unconditional jump to {@link #destination()}.
+     * When the LIR is constructed, the last operation of every block must implement this interface. After
+     * register allocation, unnecessary jumps can be deleted.
+     *
+     * TODO Currently, a block can also end with an XIR operation.
+     */
+    public static class JumpOp extends LIRInstruction {
+        private final LabelRef destination;
+
+        protected JumpOp(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps, LabelRef destination) {
+            super(opcode, outputs, info, inputs, alives, temps);
+            this.destination = destination;
+        }
+
+        public JumpOp(LabelRef destination, LIRDebugInfo info) {
+            this("JUMP", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, destination);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm) {
+            tasm.asm.jmp(destination.label());
+        }
+
+        @Override
+        public String operationString() {
+            return  destination + " " + super.operationString();
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        public LabelRef destination() {
+            return destination;
+        }
+    }
+
+    public static class PhiJumpOp extends JumpOp {
+        public PhiJumpOp(LabelRef destination, CiValue[] phiInputs) {
+            super("PHI_JUMP", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, phiInputs, LIRInstruction.NO_OPERANDS, destination);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Alive) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        public void markResolved() {
+            alives = EMPTY;
+        }
+
+        public CiValue[] getPhiInputs() {
+            return alives;
+        }
+    }
+
+    /**
+     * Marker interface for a LIR operation that is a conditional jump to {@link #destination()}.
+     * Conditional jumps may be negated or optimized away after register allocation.
+     */
+    public interface BranchOp {
+        LabelRef destination();
+        void negate(LabelRef newDestination);
+    }
+
+    /**
+     * Marker interface for a LIR operation that moves a value from {@link #getInput()} to {@link #getResult()}.
+     */
+    public interface MoveOp {
+        CiValue getInput();
+        CiValue getResult();
+    }
+
+    /**
+     * Marker interface for a LIR operation that calls a method, i.e., destroys all caller-saved registers.
+     */
+    public interface CallOp {
+    }
+
+
+    /**
+     * Meta-operation that defines the incoming method parameters. In the LIR, every register and variable must be
+     * defined before it is used. This operation is the definition point of method parameters, but is otherwise a no-op.
+     * In particular, it is not the actual method prologue.
+     */
+    public static final class ParametersOp extends LIRInstruction {
+        public ParametersOp(CiValue[] params) {
+            super("PARAMS", params, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm) {
+            // No code to emit.
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Output) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/ValueUtil.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir;
+
+import com.oracle.max.cri.ci.*;
+
+public class ValueUtil extends CiValueUtil {
+
+    public static boolean isVariable(CiValue value) {
+        assert value != null;
+        return value instanceof Variable;
+    }
+
+    public static Variable asVariable(CiValue value) {
+        assert value != null;
+        return (Variable) value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/Variable.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir;
+
+import com.oracle.max.cri.ci.*;
+
+/**
+ * Represents a value that is yet to be bound to a machine location (such as
+ * a {@link CiRegisterValue} or {@link CiStackSlot}) by a register allocator.
+ */
+public final class Variable extends CiValue {
+    private static final long serialVersionUID = 4507578431686109809L;
+
+    /**
+     * The identifier of the variable. This is a non-zero index in a contiguous 0-based name space.
+     */
+    public final int index;
+
+    /**
+     * The type of register that this variable needs to get assigned.
+     */
+    public final CiRegister.RegisterFlag flag;
+
+    /**
+     * Creates a new variable.
+     * @param kind
+     * @param index
+     */
+    public Variable(CiKind kind, int index, CiRegister.RegisterFlag flag) {
+        super(kind);
+        assert kind == kind.stackKind() : "Variables can be only created for stack kinds";
+        assert index >= 0;
+        this.index = index;
+        this.flag = flag;
+    }
+
+    @Override
+    public int hashCode() {
+        return (index << 4) | kind.ordinal();
+    }
+
+    @Override
+    public String toString() {
+        return "v" + index + kindSuffix();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/asm/TargetMethodAssembler.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.asm;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.max.asm.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.LIR.*;
+
+public class TargetMethodAssembler {
+
+    private static class ExceptionInfo {
+        public final int codeOffset;
+        public final LabelRef exceptionEdge;
+
+        public ExceptionInfo(int pcOffset, LabelRef exceptionEdge) {
+            this.codeOffset = pcOffset;
+            this.exceptionEdge = exceptionEdge;
+        }
+    }
+
+    public final AbstractAssembler asm;
+    public final CiTargetMethod targetMethod;
+    public final CiTarget target;
+    public final RiRuntime runtime;
+    public final FrameMap frameMap;
+    public final List<SlowPath> slowPaths;
+
+    private List<ExceptionInfo> exceptionInfoList;
+    private int lastSafepointPos;
+
+    public TargetMethodAssembler(CiTarget target, RiRuntime runtime, FrameMap frameMap, List<SlowPath> slowPaths, AbstractAssembler asm) {
+        this.target = target;
+        this.runtime = runtime;
+        this.frameMap = frameMap;
+        this.slowPaths = slowPaths;
+        this.asm = asm;
+        this.targetMethod = new CiTargetMethod();
+        // 0 is a valid pc for safepoints in template methods
+        this.lastSafepointPos = -1;
+    }
+
+    public void setFrameSize(int frameSize) {
+        targetMethod.setFrameSize(frameSize);
+    }
+
+    public CiTargetMethod.Mark recordMark(Object id, CiTargetMethod.Mark[] references) {
+        return targetMethod.recordMark(asm.codeBuffer.position(), id, references);
+    }
+
+    public void blockComment(String s) {
+        targetMethod.addAnnotation(new CiTargetMethod.CodeComment(asm.codeBuffer.position(), s));
+    }
+
+    public CiTargetMethod finishTargetMethod(Object name, boolean isStub) {
+        // Install code, data and frame size
+        targetMethod.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position());
+
+        // Record exception handlers if they exist
+        if (exceptionInfoList != null) {
+            for (ExceptionInfo ei : exceptionInfoList) {
+                int codeOffset = ei.codeOffset;
+                targetMethod.recordExceptionHandler(codeOffset, -1, 0, ei.exceptionEdge.label().position(), -1, null);
+            }
+        }
+
+        Debug.metric("TargetMethods").increment();
+        Debug.metric("CodeBytesEmitted").add(targetMethod.targetCodeSize());
+        Debug.metric("SafepointsEmitted").add(targetMethod.safepoints.size());
+        Debug.metric("DataPatches").add(targetMethod.dataReferences.size());
+        Debug.metric("ExceptionHandlersEmitted").add(targetMethod.exceptionHandlers.size());
+
+        Debug.log("Finished target method %s, isStub %d", name, isStub);
+/*
+        if (GraalOptions.PrintAssembly && !TTY.isSuppressed() && !isStub) {
+            Util.printSection("Target Method", Util.SECTION_CHARACTER);
+            TTY.println("Name: " + name);
+            TTY.println("Frame size: " + targetMethod.frameSize());
+            TTY.println("Register size: " + asm.target.arch.registerReferenceMapBitCount);
+
+            if (GraalOptions.PrintCodeBytes) {
+                Util.printSection("Code", Util.SUB_SECTION_CHARACTER);
+                TTY.println("Code: %d bytes", targetMethod.targetCodeSize());
+                Util.printBytes(0L, targetMethod.targetCode(), 0, targetMethod.targetCodeSize(), GraalOptions.PrintAssemblyBytesPerLine);
+            }
+
+            Util.printSection("Disassembly", Util.SUB_SECTION_CHARACTER);
+            String disassembly = runtime.disassemble(targetMethod);
+            TTY.println(disassembly);
+            boolean noDis = disassembly == null || disassembly.length() == 0;
+
+            Util.printSection("Safepoints", Util.SUB_SECTION_CHARACTER);
+            for (CiTargetMethod.Safepoint x : targetMethod.safepoints) {
+                TTY.println(x.toString());
+                if (noDis && x.debugInfo != null) {
+                    TTY.println(CiUtil.indent(x.debugInfo.toString(), "  "));
+                }
+            }
+
+            Util.printSection("Data Patches", Util.SUB_SECTION_CHARACTER);
+            for (CiTargetMethod.DataPatch x : targetMethod.dataReferences) {
+                TTY.println(x.toString());
+            }
+
+            Util.printSection("Marks", Util.SUB_SECTION_CHARACTER);
+            for (CiTargetMethod.Mark x : targetMethod.marks) {
+                TTY.println(x.toString());
+            }
+
+            Util.printSection("Exception Handlers", Util.SUB_SECTION_CHARACTER);
+            for (CiTargetMethod.ExceptionHandler x : targetMethod.exceptionHandlers) {
+                TTY.println(x.toString());
+            }
+        }
+*/
+
+        return targetMethod;
+    }
+
+    public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) {
+        if (info != null) {
+            if (info.exceptionEdge != null) {
+                if (exceptionInfoList == null) {
+                    exceptionInfoList = new ArrayList<>(4);
+                }
+                exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionEdge));
+            }
+        }
+    }
+
+    public void recordImplicitException(int pcOffset, LIRDebugInfo info) {
+        // record an implicit exception point
+        if (info != null) {
+            assert lastSafepointPos < pcOffset : lastSafepointPos + "<" + pcOffset;
+            lastSafepointPos = pcOffset;
+            targetMethod.recordSafepoint(pcOffset, info.debugInfo());
+            assert info.exceptionEdge == null;
+        }
+    }
+
+    public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRDebugInfo info) {
+        CiDebugInfo debugInfo = info != null ? info.debugInfo() : null;
+        assert lastSafepointPos < posAfter;
+        lastSafepointPos = posAfter;
+        targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, true);
+    }
+
+    public void recordIndirectCall(int posBefore, int posAfter, Object callTarget, LIRDebugInfo info) {
+        CiDebugInfo debugInfo = info != null ? info.debugInfo() : null;
+        assert lastSafepointPos < posAfter;
+        lastSafepointPos = posAfter;
+        targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false);
+    }
+
+    public void recordSafepoint(int pos, LIRDebugInfo info) {
+        // safepoints always need debug info
+        CiDebugInfo debugInfo = info.debugInfo();
+        assert lastSafepointPos < pos;
+        lastSafepointPos = pos;
+        targetMethod.recordSafepoint(pos, debugInfo);
+    }
+
+    public CiAddress recordDataReferenceInCode(CiConstant data, int alignment) {
+        assert data != null;
+        int pos = asm.codeBuffer.position();
+        Debug.log("Data reference in code: pos = %d, data = %s", pos, data.toString());
+        targetMethod.recordDataReference(pos, data, alignment);
+        return CiAddress.Placeholder;
+    }
+
+    public int lastSafepointPos() {
+        return lastSafepointPos;
+    }
+
+
+    /**
+     * Returns the integer value of any constants that can be represented by a 32-bit integer value,
+     * including long constants that fit into the 32-bit range.
+     */
+    public int asIntConst(CiValue value) {
+        assert (value.kind.stackKind() == CiKind.Int || value.kind == CiKind.Jsr || value.kind == CiKind.Long) && isConstant(value);
+        long c = ((CiConstant) value).asLong();
+        if (!(NumUtil.isInt(c))) {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+        return (int) c;
+    }
+
+    /**
+     * Returns the address of a float constant that is embedded as a data references into the code.
+     */
+    public CiAddress asFloatConstRef(CiValue value) {
+        return asFloatConstRef(value, 4);
+    }
+
+    public CiAddress asFloatConstRef(CiValue value, int alignment) {
+        assert value.kind == CiKind.Float && isConstant(value);
+        return recordDataReferenceInCode((CiConstant) value, alignment);
+    }
+
+    /**
+     * Returns the address of a double constant that is embedded as a data references into the code.
+     */
+    public CiAddress asDoubleConstRef(CiValue value) {
+        return asDoubleConstRef(value, 8);
+    }
+
+    public CiAddress asDoubleConstRef(CiValue value, int alignment) {
+        assert value.kind == CiKind.Double && isConstant(value);
+        return recordDataReferenceInCode((CiConstant) value, alignment);
+    }
+
+    /**
+     * Returns the address of a long constant that is embedded as a data references into the code.
+     */
+    public CiAddress asLongConstRef(CiValue value) {
+        assert value.kind == CiKind.Long && isConstant(value);
+        return recordDataReferenceInCode((CiConstant) value, 8);
+    }
+
+    public CiAddress asIntAddr(CiValue value) {
+        assert value.kind == CiKind.Int;
+        return asAddress(value);
+    }
+
+    public CiAddress asLongAddr(CiValue value) {
+        assert value.kind == CiKind.Long;
+        return asAddress(value);
+    }
+
+    public CiAddress asObjectAddr(CiValue value) {
+        assert value.kind == CiKind.Object;
+        return asAddress(value);
+    }
+
+    public CiAddress asFloatAddr(CiValue value) {
+        assert value.kind == CiKind.Float;
+        return asAddress(value);
+    }
+
+    public CiAddress asDoubleAddr(CiValue value) {
+        assert value.kind == CiKind.Double;
+        return asAddress(value);
+    }
+
+    public CiAddress asAddress(CiValue value) {
+        if (isStackSlot(value)) {
+            CiStackSlot slot = (CiStackSlot) value;
+            return new CiAddress(slot.kind, frameMap.registerConfig.getFrameRegister().asValue(), frameMap.offsetForStackSlot(slot));
+        }
+        return (CiAddress) value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/Block.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.cfg;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.nodes.java.*;
+
+public class Block {
+    protected int id;
+
+    protected BeginNode beginNode;
+    protected Node endNode;
+    protected Loop loop;
+    protected double probability;
+
+    protected List<Block> predecessors;
+    protected List<Block> successors;
+
+    protected Block dominator;
+    protected List<Block> dominated;
+    protected Block postdominator;
+
+    // Fields that still need to be worked on, try to remove them later.
+    public List<LIRInstruction> lir;
+    public boolean align;
+    public int linearScanNumber;
+
+    public Block() {
+        id = ControlFlowGraph.BLOCK_ID_INITIAL;
+    }
+
+    public int getId() {
+        assert id >= 0;
+        return id;
+    }
+
+    public BeginNode getBeginNode() {
+        return beginNode;
+    }
+
+    public Node getEndNode() {
+        return endNode;
+    }
+
+    public Loop getLoop() {
+        return loop;
+    }
+
+    public int getLoopDepth() {
+        return loop == null ? 0 : loop.depth;
+    }
+
+    public boolean isLoopHeader() {
+        return getBeginNode() instanceof LoopBeginNode;
+    }
+
+    public boolean isLoopEnd() {
+        return getEndNode() instanceof LoopEndNode;
+    }
+
+    public boolean isExceptionEntry() {
+        return getBeginNode().next() instanceof ExceptionObjectNode;
+    }
+
+    public List<Block> getPredecessors() {
+        return predecessors;
+    }
+
+    public List<Block> getSuccessors() {
+        return successors;
+    }
+
+    public Block getDominator() {
+        return dominator;
+    }
+
+    public List<Block> getDominated() {
+        if (dominated == null) {
+            return Collections.emptyList();
+        }
+        return dominated;
+    }
+
+    public Block getPostdominator() {
+        return postdominator;
+    }
+
+    private class NodeIterator implements Iterator<Node> {
+        private Node cur;
+
+        public NodeIterator() {
+            cur = getBeginNode();
+        }
+
+        @Override
+        public boolean hasNext() {
+            return cur != null;
+        }
+
+        @Override
+        public Node next() {
+            Node result = cur;
+            if (cur == getEndNode()) {
+                cur = null;
+            } else {
+                cur = ((FixedWithNextNode) cur).next();
+            }
+            assert !(cur instanceof BeginNode);
+            return result;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    public Iterable<Node> getNodes() {
+        return new Iterable<Node>() {
+            @Override
+            public Iterator<Node> iterator() {
+                return new NodeIterator();
+            }
+        };
+    }
+
+    public int getFirstLirInstructionId() {
+        int result = lir.get(0).id();
+        assert result >= 0;
+        return result;
+    }
+
+    public int getLastLirInstructionId() {
+        int result = lir.get(lir.size() - 1).id();
+        assert result >= 0;
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "B" + id;
+    }
+
+
+// to be inlined later on
+    public int numberOfPreds() {
+        return getPredecessors().size();
+    }
+
+    public int numberOfSux() {
+        return getSuccessors().size();
+    }
+
+    public Block predAt(int i) {
+        return getPredecessors().get(i);
+    }
+
+    public Block suxAt(int i) {
+        return getSuccessors().get(i);
+    }
+// end to be inlined later on
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/BlockMap.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.cfg;
+
+public class BlockMap<T> {
+    private final T[] data;
+
+    @SuppressWarnings("unchecked")
+    public BlockMap(ControlFlowGraph cfg) {
+        data = (T[]) new Object[cfg.getBlocks().length];
+    }
+
+    public T get(Block block) {
+        return data[block.getId()];
+    }
+
+    public void put(Block block, T value) {
+        data[block.getId()] = value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/CFGVerifier.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.cfg;
+
+public class CFGVerifier {
+    public static boolean verify(ControlFlowGraph cfg) {
+        for (Block block : cfg.getBlocks()) {
+            assert cfg.getBlocks()[block.getId()] == block;
+
+            for (Block pred : block.getPredecessors()) {
+                assert pred.getSuccessors().contains(block);
+                assert pred.getId() < block.getId() || pred.isLoopEnd();
+            }
+
+            for (Block sux : block.getSuccessors()) {
+                assert sux.getPredecessors().contains(block);
+                assert sux.getId() > block.getId() || sux.isLoopHeader();
+            }
+
+            if (block.getDominator() != null) {
+                assert block.getDominator().getId() < block.getId();
+                assert block.getDominator().getDominated().contains(block);
+            }
+            for (Block dominated : block.getDominated()) {
+                assert dominated.getId() > block.getId();
+                assert dominated.getDominator() == block;
+            }
+
+            assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().header == block;
+        }
+
+        if (cfg.getLoops() != null) {
+            for (Loop loop : cfg.getLoops()) {
+                assert loop.header.isLoopHeader();
+
+                for (Block block : loop.blocks) {
+                    assert block.getId() >= loop.header.getId();
+
+                    Loop blockLoop = block.getLoop();
+                    while (blockLoop != loop) {
+                        blockLoop = blockLoop.parent;
+                        assert blockLoop != null;
+                    }
+                }
+
+                for (Block block : loop.exits) {
+                    assert block.getId() >= loop.header.getId();
+
+                    Loop blockLoop = block.getLoop();
+                    while (blockLoop != null) {
+                        blockLoop = blockLoop.parent;
+                        assert blockLoop != loop;
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/ControlFlowGraph.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.cfg;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.nodes.*;
+
+public class ControlFlowGraph {
+
+    public final StructuredGraph graph;
+
+    private final NodeMap<Block> nodeToBlock;
+    private Block[] reversePostOrder;
+    private Loop[] loops;
+
+    public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) {
+        ControlFlowGraph cfg = new ControlFlowGraph(graph);
+        cfg.identifyBlocks();
+        if (connectBlocks || computeLoops || computeDominators || computePostdominators) {
+            cfg.connectBlocks();
+        }
+        if (computeLoops) {
+            cfg.computeLoopInformation();
+        }
+        if (computeDominators) {
+            cfg.computeDominators();
+        }
+        if (computePostdominators) {
+            cfg.computePostdominators();
+        }
+        assert CFGVerifier.verify(cfg);
+        return cfg;
+    }
+
+    protected ControlFlowGraph(StructuredGraph graph) {
+        this.graph = graph;
+        this.nodeToBlock = graph.createNodeMap();
+    }
+
+    public Block[] getBlocks() {
+        return reversePostOrder;
+    }
+
+    public Block getStartBlock() {
+        return reversePostOrder[0];
+    }
+
+    public NodeMap<Block> getNodeToBlock() {
+        return nodeToBlock;
+    }
+
+    public Block blockFor(Node node) {
+        return nodeToBlock.get(node);
+    }
+
+    public Loop[] getLoops() {
+        return loops;
+    }
+
+    protected static final int BLOCK_ID_INITIAL = -1;
+    protected static final int BLOCK_ID_VISITED = -2;
+
+    private void identifyBlocks() {
+        // Find all block headers
+        int numBlocks = 0;
+        for (Node node : graph.getNodes()) {
+            if (node instanceof BeginNode) {
+                Block block = new Block();
+                numBlocks++;
+
+                block.beginNode = (BeginNode) node;
+                Node cur = node;
+                do {
+                    assert !cur.isDeleted();
+                    block.endNode = cur;
+
+                    assert nodeToBlock.get(cur) == null;
+                    nodeToBlock.set(cur, block);
+                    if (cur instanceof MergeNode) {
+                        for (PhiNode phi : ((MergeNode) cur).phis()) {
+                            nodeToBlock.set(phi, block);
+                        }
+                    }
+
+                    if (cur instanceof FixedNode) {
+                        double probability = ((FixedNode) cur).probability();
+                        if (probability > block.probability) {
+                            block.probability = probability;
+                        }
+                    }
+
+                    Node next = null;
+                    for (Node sux : cur.successors()) {
+                        if (sux != null && !(sux instanceof BeginNode)) {
+                            assert next == null;
+                            next = sux;
+                        }
+                    }
+                    cur = next;
+                } while (cur != null);
+            }
+        }
+
+        // Compute reverse postorder.
+        reversePostOrder = new Block[numBlocks];
+        int reversePostOrderId = numBlocks - 1;
+
+        ArrayList<Block> stack = new ArrayList<>();
+        stack.add(blockFor(graph.start()));
+
+        do {
+            Block block = stack.get(stack.size() - 1);
+            if (block.id == BLOCK_ID_INITIAL) {
+                // First time we see this block: push all successors.
+                for (Node suxNode : block.getEndNode().cfgSuccessors()) {
+                    Block suxBlock = blockFor(suxNode);
+                    assert suxBlock.id != BLOCK_ID_VISITED;
+                    if (suxBlock.id == BLOCK_ID_INITIAL) {
+                        stack.add(suxBlock);
+                    }
+                }
+                block.id = BLOCK_ID_VISITED;
+            } else if (block.id == BLOCK_ID_VISITED) {
+                // Second time we see this block: All successors haved been processed, so insert block into reverse postorder list.
+                stack.remove(stack.size() - 1);
+                reversePostOrder[reversePostOrderId] = block;
+                block.id = reversePostOrderId;
+                reversePostOrderId--;
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        } while (!stack.isEmpty());
+        assert reversePostOrderId == -1;
+    }
+
+    // Connect blocks (including loop backward edges).
+    private void connectBlocks() {
+        for (Block block : reversePostOrder) {
+            List<Block> predecessors = new ArrayList<>();
+            for (Node predNode : block.getBeginNode().cfgPredecessors()) {
+                predecessors.add(nodeToBlock.get(predNode));
+            }
+            if (block.getBeginNode() instanceof LoopBeginNode) {
+                predecessors.add(nodeToBlock.get(((LoopBeginNode) block.getBeginNode()).loopEnd()));
+            }
+            block.predecessors = predecessors;
+
+            List<Block> successors = new ArrayList<>();
+            for (Node suxNode : block.getEndNode().cfgSuccessors()) {
+                successors.add(nodeToBlock.get(suxNode));
+            }
+            if (block.getEndNode() instanceof LoopEndNode) {
+                successors.add(nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin()));
+            }
+            block.successors = successors;
+        }
+    }
+
+    private void computeLoopInformation() {
+        List<Loop> loopsList = new ArrayList<>();
+        for (Block block : reversePostOrder) {
+            Node beginNode = block.getBeginNode();
+            if (beginNode instanceof LoopBeginNode) {
+                Loop loop = new Loop(block.getLoop(), loopsList.size(), block);
+                loopsList.add(loop);
+
+                LoopEndNode end = ((LoopBeginNode) beginNode).loopEnd();
+                Block endBlock = nodeToBlock.get(end);
+                computeLoopBlocks(endBlock, loop);
+            }
+        }
+        loops = loopsList.toArray(new Loop[loopsList.size()]);
+
+        for (Loop loop : loops) {
+            for (Block block : loop.blocks) {
+                for (Block sux : block.getSuccessors()) {
+                    if (sux.getLoopDepth() < loop.depth) {
+                        loop.exits.add(sux);
+                    }
+                }
+            }
+        }
+    }
+
+    private void computeLoopBlocks(Block block, Loop loop) {
+        if (block.getLoop() == loop) {
+            return;
+        }
+        assert block.loop == loop.parent;
+        block.loop = loop;
+
+        assert !loop.blocks.contains(block);
+        loop.blocks.add(block);
+
+        if (block != loop.header) {
+            for (Block pred : block.getPredecessors()) {
+                computeLoopBlocks(pred, loop);
+            }
+        }
+    }
+
+    private void computeDominators() {
+        assert reversePostOrder[0].getPredecessors().size() == 0 : "start block has no predecessor and therefore no dominator";
+        for (int i = 1; i < reversePostOrder.length; i++) {
+            Block block = reversePostOrder[i];
+            List<Block> predecessors = block.getPredecessors();
+            assert predecessors.size() > 0;
+
+            if (block.isLoopHeader()) {
+                // Loop headers have exactly one non-loop predecessor, and that is the dominator.
+                setDominator(block, predecessors.get(0));
+                continue;
+            }
+
+            Block dominator = predecessors.get(0);
+            for (int j = 1; j < predecessors.size(); j++) {
+                Block pred = predecessors.get(j);
+                dominator = commonDominator(dominator, pred);
+            }
+            setDominator(block, dominator);
+        }
+    }
+
+    private static void setDominator(Block block, Block dominator) {
+        block.dominator = dominator;
+        if (dominator.dominated == null) {
+            dominator.dominated = new ArrayList<>();
+        }
+        dominator.dominated.add(block);
+    }
+
+    public static Block commonDominator(Block a, Block b) {
+        Block iterA = a;
+        Block iterB = b;
+        while (iterA != iterB) {
+            if (iterA.getId() > iterB.getId()) {
+                iterA = iterA.getDominator();
+            } else {
+                assert iterB.getId() > iterA.getId();
+                iterB = iterB.getDominator();
+            }
+        }
+        return iterA;
+    }
+
+    private void computePostdominators() {
+        for (Block block : reversePostOrder) {
+            if (block.isLoopEnd()) {
+                // We do not want the loop header registered as the postdominator of the loop end.
+                continue;
+            }
+            Block postdominator = null;
+            for (Block sux : block.getSuccessors()) {
+                if (sux.isExceptionEntry()) {
+                    // We ignore exception handlers.
+                } else if (postdominator == null) {
+                    postdominator = sux;
+                } else {
+                    postdominator = commonPostdominator(postdominator, sux);
+                }
+            }
+            block.postdominator = postdominator;
+        }
+    }
+
+    private static Block commonPostdominator(Block a, Block b) {
+        Block iterA = a;
+        Block iterB = b;
+        while (iterA != iterB) {
+            if (iterA.getId() < iterB.getId()) {
+                iterA = iterA.getPostdominator();
+                if (iterA == null) {
+                    return null;
+                }
+            } else {
+                assert iterB.getId() < iterA.getId();
+                iterB = iterB.getPostdominator();
+                if (iterB == null) {
+                    return null;
+                }
+            }
+        }
+        return iterA;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/Loop.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.max.graal.lir.cfg;
+
+import java.util.*;
+
+public class Loop {
+    public final Loop parent;
+    public final List<Loop> children;
+
+    public final int depth;
+    public final int index;
+    public final Block header;
+    public final List<Block> blocks;
+    public final List<Block> exits;
+
+    protected Loop(Loop parent, int index, Block header) {
+        this.parent = parent;
+        if (parent != null) {
+            this.depth = parent.depth + 1;
+            parent.children.add(this);
+        } else {
+            this.depth = 1;
+        }
+        this.index = index;
+        this.header = header;
+        this.blocks = new ArrayList<>();
+        this.children = new ArrayList<>();
+        this.exits = new ArrayList<>();
+    }
+
+    @Override
+    public String toString() {
+        return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : "");
+    }
+}
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/type/StampFactory.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/type/StampFactory.java	Wed Feb 08 21:15:00 2012 -0800
@@ -173,7 +173,7 @@
             RiResolvedType exactType = first.exactType();
             while (iterator.hasNext()) {
                 Stamp current = iterator.next().stamp();
-                assert current.kind() == first.kind() : values + " first=" + first + " current=" + current;
+                assert current.kind() == first.kind() : values + " first=" + first + " current=" + current + " first kind=" + first.kind() + " current kind=" + current.kind();
                 nonNull &= current.nonNull();
                 declaredType = orTypes(declaredType, current.declaredType());
                 exactType = orTypes(exactType, current.exactType());
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -33,15 +33,15 @@
 import com.oracle.max.graal.alloc.util.*;
 import com.oracle.max.graal.compiler.alloc.*;
 import com.oracle.max.graal.compiler.alloc.Interval.UsePosList;
-import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.graph.Node.Verbosity;
 import com.oracle.max.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.max.graal.graph.NodeClass.Position;
 import com.oracle.max.graal.java.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.calc.*;
 
@@ -50,7 +50,6 @@
  */
 class CFGPrinter extends CompilationPrinter {
 
-    public final ByteArrayOutputStream buffer;
     public final CiTarget target;
     public final RiRuntime runtime;
     public LIR lir;
@@ -61,9 +60,8 @@
      *
      * @param buffer where the output generated via this printer shown be written
      */
-    public CFGPrinter(ByteArrayOutputStream buffer, CiTarget target, RiRuntime runtime) {
-        super(buffer);
-        this.buffer = buffer;
+    public CFGPrinter(OutputStream out, CiTarget target, RiRuntime runtime) {
+        super(out);
         this.target = target;
         this.runtime = runtime;
     }
@@ -347,22 +345,6 @@
         begin("IR");
         out.println("LIR");
 
-        if (block.phis != null) {
-            CiValue[] results = block.phis.results();
-            for (int i = 0; i < results.length; i++) {
-                if (i == 0) {
-                    out.printf("nr %4d ", block.getFirstLirInstructionId()).print(COLUMN_END);
-                }
-                out.print("instruction PHI ").print(results[i].toString()).print(" = (");
-                String sep = "";
-                for (Block pred : block.getPredecessors()) {
-                    out.print(sep).print(block.phis.inputs(pred)[i].toString());
-                    sep = ", ";
-                }
-                out.print(")").print(COLUMN_END).println(COLUMN_END);
-            }
-        }
-
         for (int i = 0; i < lirInstructions.size(); i++) {
             LIRInstruction inst = lirInstructions.get(i);
             out.printf("nr %4d ", inst.id()).print(COLUMN_END);
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Wed Feb 08 21:15:00 2012 -0800
@@ -27,118 +27,98 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.criutils.*;
 import com.oracle.max.graal.alloc.util.*;
+import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.alloc.*;
 import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.observer.*;
 import com.oracle.max.graal.compiler.schedule.*;
-import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.java.*;
+import com.oracle.max.graal.lir.*;
 import com.oracle.max.graal.nodes.*;
 
 /**
  * Observes compilation events and uses {@link CFGPrinter} to produce a control flow graph for the <a
  * href="http://java.net/projects/c1visualizer/">C1 Visualizer</a>.
  */
-public class CFGPrinterObserver implements CompilationObserver {
+public class CFGPrinterObserver implements DebugDumpHandler {
+
+    private CFGPrinter cfgPrinter;
 
-    /**
-     * A thread local stack of {@link CFGPrinter}s to support thread-safety and re-entrant compilation.
-     */
-    private ThreadLocal<LinkedList<CFGPrinter>> observations = new ThreadLocal<LinkedList<CFGPrinter>>() {
-        @Override
-        protected java.util.LinkedList<CFGPrinter> initialValue() {
-            return new LinkedList<>();
-        }
-    };
+    private GraalCompiler compiler;
+    private RiResolvedMethod method;
+    private SchedulePhase schedule;
 
     @Override
-    public void compilationStarted(CompilationEvent event) {
-        if (TTY.isSuppressed()) {
+    public void dump(final Object object, final String message) {
+        Debug.sandbox("CFGPrinter", new Runnable() {
+            @Override
+            public void run() {
+                dumpSandboxed(object, message);
+            }
+        });
+    }
+
+    private void dumpSandboxed(final Object object, final String message) {
+        if (object instanceof GraalCompiler) {
+            compiler = (GraalCompiler) object;
+            return;
+        } else if (object instanceof SchedulePhase) {
+            schedule = (SchedulePhase) object;
+            return;
+        } else if (object instanceof LIRGenerator) {
+            cfgPrinter.lirGenerator = (LIRGenerator) object;
             return;
         }
-        RiRuntime runtime = event.debugObject(RiRuntime.class);
-        CiTarget target = event.debugObject(CiTarget.class);
 
-        CFGPrinter cfgPrinter = new CFGPrinter(new ByteArrayOutputStream(), target, runtime);
-        cfgPrinter.printCompilation(event.debugObject(RiResolvedMethod.class));
-        observations.get().push(cfgPrinter);
-    }
-
-    @Override
-    public void compilationEvent(CompilationEvent event) {
-        if (TTY.isSuppressed()) {
-            return;
-        }
-        CFGPrinter cfgPrinter = observations.get().peek();
         if (cfgPrinter == null) {
-            return;
+            File file = new File("compilations-" + System.currentTimeMillis() + ".cfg");
+            try {
+                OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
+                cfgPrinter = new CFGPrinter(out, compiler.target, compiler.runtime);
+            } catch (FileNotFoundException e) {
+                throw new InternalError("Could not open " + file.getAbsolutePath());
+            }
         }
 
         RiRuntime runtime = cfgPrinter.runtime;
-        if (event.debugObject(LIR.class) != null) {
-            cfgPrinter.lir = event.debugObject(LIR.class);
-        }
-        if (event.debugObject(LIRGenerator.class) != null) {
-            cfgPrinter.lirGenerator = event.debugObject(LIRGenerator.class);
+        if (object instanceof RiResolvedMethod) {
+            method = (RiResolvedMethod) object;
+            cfgPrinter.printCompilation(method);
+
+            cfgPrinter.lir = null;
+            cfgPrinter.lirGenerator = null;
+            schedule = null;
+
+        } else if (object instanceof BciBlockMapping) {
+            BciBlockMapping blockMap = (BciBlockMapping) object;
+            cfgPrinter.printCFG(message, blockMap);
+            cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method));
+
+        } else if (object instanceof LIR) {
+            cfgPrinter.lir = (LIR) object;
+            cfgPrinter.printCFG(message, ((LIR) object).codeEmittingOrder(), schedule);
+
+        } else if (object instanceof StructuredGraph) {
+            SchedulePhase curSchedule = schedule;
+            if (curSchedule == null) {
+                try {
+                    curSchedule = new SchedulePhase();
+                    curSchedule.apply((StructuredGraph) object);
+                } catch (Throwable ex) {
+                    // ignore
+                }
+            }
+            cfgPrinter.printCFG(message, Arrays.asList(curSchedule.getCFG().getBlocks()), curSchedule);
+
+        } else if (object instanceof CiTargetMethod) {
+            cfgPrinter.printMachineCode(runtime.disassemble((CiTargetMethod) object), null);
+        } else if (object instanceof Interval[]) {
+            cfgPrinter.printIntervals(message, (Interval[]) object);
+        } else if (object instanceof IntervalPrinter.Interval[]) {
+            cfgPrinter.printIntervals(message, (IntervalPrinter.Interval[]) object);
         }
 
-        BciBlockMapping blockMap = event.debugObject(BciBlockMapping.class);
-        Graph graph = event.debugObject(Graph.class);
-        SchedulePhase schedule = event.debugObject(SchedulePhase.class);
-        LinearScan allocator = event.debugObject(LinearScan.class);
-        Interval[] intervals = event.debugObject(Interval[].class);
-        IntervalPrinter.Interval[] printIntervals = event.debugObject(IntervalPrinter.Interval[].class);
-        CiTargetMethod targetMethod = event.debugObject(CiTargetMethod.class);
-
-        if (blockMap != null) {
-            cfgPrinter.printCFG(event.label, blockMap);
-            cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method));
-        }
-        if (cfgPrinter.lir != null) {
-            cfgPrinter.printCFG(event.label, cfgPrinter.lir.codeEmittingOrder(), schedule);
-            if (targetMethod != null) {
-                cfgPrinter.printMachineCode(runtime.disassemble(targetMethod), null);
-            }
-        } else if (graph != null) {
-            if (schedule == null) {
-                try {
-                    schedule = new SchedulePhase();
-                    schedule.apply((StructuredGraph) graph);
-                } catch (Throwable t) {
-                    // nothing to do here...
-                }
-            }
-            cfgPrinter.printCFG(event.label, Arrays.asList(schedule.getCFG().getBlocks()), schedule);
-        }
-        if (allocator != null && intervals != null) {
-            cfgPrinter.printIntervals(event.label, intervals);
-        }
-        if (printIntervals != null) {
-            cfgPrinter.printIntervals(event.label, printIntervals);
-        }
-    }
-
-    @Override
-    public void compilationFinished(CompilationEvent event) {
-        if (TTY.isSuppressed()) {
-            return;
-        }
-        CFGPrinter cfgPrinter = observations.get().pop();
         cfgPrinter.flush();
-
-        OutputStream stream = CompilationPrinter.globalOut();
-        if (stream != null) {
-            synchronized (stream) {
-                try {
-                    stream.write(cfgPrinter.buffer.toByteArray());
-                    stream.flush();
-                } catch (IOException e) {
-                    TTY.println("WARNING: Error writing CFGPrinter output: %s", e);
-                }
-            }
-        }
     }
 }
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinter.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -27,13 +27,13 @@
 import java.util.Map.Entry;
 
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.graph.Node.Verbosity;
 import com.oracle.max.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.max.graal.graph.NodeClass.Position;
 import com.oracle.max.graal.java.*;
+import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 
 /**
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinterDumpHandler.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinterDumpHandler.java	Wed Feb 08 21:15:00 2012 -0800
@@ -25,6 +25,7 @@
 import java.io.*;
 import java.net.*;
 import java.util.*;
+
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.criutils.*;
@@ -40,7 +41,7 @@
     private static final String DEFAULT_FILE_NAME = "output.igv.xml";
 
     private IdealGraphPrinter printer;
-    private List<RiResolvedMethod> previousInlineContext = new ArrayList<>();
+    private List<String> previousInlineContext = new ArrayList<>();
     private String fileName;
     private String host;
     private int port;
@@ -61,8 +62,6 @@
         this.port = port;
     }
 
-
-
     private void ensureInitialized() {
         if (!initialized) {
             initialized = true;
@@ -85,7 +84,7 @@
     }
 
     private void initializeNetworkPrinter() {
-        try  {
+        try {
             Socket socket = new Socket(host, port);
             BufferedOutputStream stream = new BufferedOutputStream(socket.getOutputStream(), 0x4000);
             printer = new IdealGraphPrinter(stream);
@@ -103,26 +102,29 @@
 
             if (printer.isValid()) {
                 // Get all current RiResolvedMethod instances in the context.
-                List<RiResolvedMethod> inlineContext = Debug.contextSnapshot(RiResolvedMethod.class);
+                List<String> inlineContext = getInlineContext();
+                Debug.contextSnapshot(RiResolvedMethod.class);
 
                 // Reverse list such that inner method comes after outer method.
                 Collections.reverse(inlineContext);
 
                 // Check for method scopes that must be closed since the previous dump.
                 for (int i = 0; i < previousInlineContext.size(); ++i) {
-                    if (i >= inlineContext.size() || inlineContext.get(i) != previousInlineContext.get(i)) {
+                    if (i >= inlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
                         for (int j = previousInlineContext.size() - 1; j >= i; --j) {
-                            closeMethodScope();
+                            closeScope();
                         }
+                        break;
                     }
                 }
 
                 // Check for method scopes that must be opened since the previous dump.
                 for (int i = 0; i < inlineContext.size(); ++i) {
-                    if (i >= previousInlineContext.size() || inlineContext.get(i) != previousInlineContext.get(i)) {
+                    if (i >= previousInlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
                         for (int j = i; j < inlineContext.size(); ++j) {
-                            openMethodScope(inlineContext.get(j));
+                            openScope(inlineContext.get(j));
                         }
+                        break;
                     }
                 }
 
@@ -145,13 +147,25 @@
         }
     }
 
-    private void openMethodScope(RiResolvedMethod method) {
-        printer.beginGroup(CiUtil.format("%H::%n", method), CiUtil.format("%h::%n", method), method, -1);
-
+    private static List<String> getInlineContext() {
+        List<String> result = new ArrayList<>();
+        for (Object o : Debug.context()) {
+            if (o instanceof RiResolvedMethod) {
+                RiResolvedMethod method = (RiResolvedMethod) o;
+                result.add(CiUtil.format("%H::%n", method));
+            } else if (o instanceof DebugDumpScope) {
+                DebugDumpScope debugDumpScope = (DebugDumpScope) o;
+                result.add(debugDumpScope.getName());
+            }
+        }
+        return result;
     }
 
-    private void closeMethodScope() {
+    private void openScope(String name) {
+        printer.beginGroup(name, name, Debug.contextLookup(RiResolvedMethod.class), -1);
+    }
+
+    private void closeScope() {
         printer.endGroup();
-
     }
 }
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/nodes/MathIntrinsicNode.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/nodes/MathIntrinsicNode.java	Wed Feb 08 21:15:00 2012 -0800
@@ -22,13 +22,13 @@
  */
 package com.oracle.max.graal.snippets.nodes;
 
-import static com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.*;
+import static com.oracle.max.graal.lir.amd64.AMD64Arithmetic.*;
 
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op2Reg;
 import com.oracle.max.graal.compiler.target.amd64.*;
-import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.Op2Reg;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.calc.*;
 import com.oracle.max.graal.nodes.spi.*;
@@ -71,7 +71,7 @@
             case SIN:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.SIN, result, input)); break;
             case COS:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.COS, result, input)); break;
             case TAN:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.TAN, result, input)); break;
-            default:    throw Util.shouldNotReachHere();
+            default:    throw GraalInternalError.shouldNotReachHere();
         }
         gen.setResult(this, result);
     }
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java	Wed Feb 08 21:15:00 2012 -0800
@@ -28,10 +28,10 @@
 
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.asm.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.target.amd64.*;
-import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.amd64.*;
+import com.oracle.max.graal.lir.asm.*;
 
 public class AMD64MathIntrinsicOp extends AMD64LIRInstruction {
     public enum Opcode  {
@@ -57,7 +57,7 @@
             case SIN:   masm.fsin(asDoubleReg(result), asDoubleReg(input)); break;
             case COS:   masm.fcos(asDoubleReg(result), asDoubleReg(input)); break;
             case TAN:   masm.ftan(asDoubleReg(result), asDoubleReg(input)); break;
-            default:    throw Util.shouldNotReachHere();
+            default:    throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -68,6 +68,6 @@
         } else if (mode == OperandMode.Output && index == 0) {
             return EnumSet.of(OperandFlag.Register);
         }
-        throw Util.shouldNotReachHere();
+        throw GraalInternalError.shouldNotReachHere();
     }
 }
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/DegeneratedLoopsTest.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/DegeneratedLoopsTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -52,9 +52,6 @@
     }
 
     private static class UnresolvedException extends RuntimeException {
-        /**
-         *
-         */
         private static final long serialVersionUID = 5215434338750728440L;
 
         static {
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphScheduleTest.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphScheduleTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -26,9 +26,9 @@
 
 import org.junit.*;
 
-import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 
 public class GraphScheduleTest extends GraphTest {
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/NestedLoopTest.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/NestedLoopTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -24,9 +24,9 @@
 
 import org.junit.*;
 
-import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 
 public class NestedLoopTest extends GraphTest {
--- a/mx/commands.py	Wed Feb 08 21:13:35 2012 -0800
+++ b/mx/commands.py	Wed Feb 08 21:15:00 2012 -0800
@@ -218,6 +218,57 @@
     
     if len(failed) != 0:
         mx.abort('DaCapo failures: ' + str(failed))
+    
+
+def scaladacapo(args):
+    """run one or all Scala DaCapo benchmarks
+    
+    Scala DaCapo options are distinguished from VM options by a '@' prefix.
+    For example, '@--iterations @5' will pass '--iterations 5' to the
+    DaCapo harness."""
+
+    numTests = {}
+    
+    if len(args) > 0:
+        level = getattr(sanitycheck.SanityCheckLevel, args[0], None)
+        if level is not None:
+            del args[0]
+            for (bench, ns) in sanitycheck.dacapoScalaSanityWarmup.items():
+                if ns[level] > 0:
+                    numTests[bench] = ns[level]
+        else:
+            while len(args) != 0 and args[0][0] not in ['-', '@']:
+                n = 1
+                if args[0].isdigit():
+                    n = int(args[0])
+                    assert len(args) > 1 and args[1][0] not in ['-', '@'] and not args[1].isdigit()
+                    bm = args[1]
+                    del args[0]
+                else:
+                    bm = args[0]
+                
+                del args[0]
+                if bm not in sanitycheck.dacapoScalaSanityWarmup.keys():
+                    mx.abort('unknown benchmark: ' + bm + '\nselect one of: ' + str(sanitycheck.dacapoScalaSanityWarmup.keys()))
+                numTests[bm] = n
+    
+    if len(numTests) is 0:    
+        for bench in sanitycheck.dacapoScalaSanityWarmup.keys():
+            numTests[bench] = 1
+    
+    # Extract DaCapo options
+    dacapoArgs = [(arg[1:]) for arg in args if arg.startswith('@')]
+    
+    # The remainder are VM options 
+    vmOpts = [arg for arg in args if not arg.startswith('@')]
+    
+    failed = []
+    for (test, n) in numTests.items():
+        if not sanitycheck.getScalaDacapo(test, n, dacapoArgs).test('graal', opts=vmOpts):
+            failed.append(test)
+    
+    if len(failed) != 0:
+        mx.abort('Scala DaCapo failures: ' + str(failed))
  
 def _jdk(build='product', create=False):
     """
@@ -498,7 +549,7 @@
         build(['--no-native'])
         tasks.append(t.stop())
     
-        for vmbuild in ['product', 'fastdebug']:
+        for vmbuild in ['fastdebug', 'product']:
             global _vmbuild
             _vmbuild = vmbuild
             
@@ -571,6 +622,15 @@
             if dacapo not in sanitycheck.dacapoSanityWarmup.keys():
                 mx.abort('Unknown dacapo : ' + dacapo)
             benchmarks += [sanitycheck.getDacapo(dacapo, sanitycheck.dacapoSanityWarmup[dacapo][sanitycheck.SanityCheckLevel.Benchmark])]
+    
+    if ('scaladacapo' in args or 'all' in args):
+        benchmarks += sanitycheck.getScalaDacapos(level=sanitycheck.SanityCheckLevel.Benchmark)
+    else:
+        dacapos = [a[7:] for a in args if a.startswith('scaladacapo:')]
+        for dacapo in dacapos:
+            if dacapo not in sanitycheck.dacapoScalaSanityWarmup.keys():
+                mx.abort('Unknown dacapo : ' + dacapo)
+            benchmarks += [sanitycheck.getScalaDacapo(dacapo, sanitycheck.dacapoScalaSanityWarmup[dacapo][sanitycheck.SanityCheckLevel.Benchmark])]
         
     #Bootstrap
     if ('bootstrap' in args or 'all' in args):
@@ -597,14 +657,29 @@
     vmArgs = [a for a in args if a[0] != '@']
     sanitycheck.getSPECjvm2008(benchArgs).bench('graal', opts=vmArgs)
     
+def hsdis(args):
+    """Installs the hsdis library
+
+    This is needed to support HotSpot's assembly dumping features.
+    By default it installs the Intel syntax version, use the 'att' argument to install AT&T syntax."""
+    flavor = 'intel'
+    if 'att' in args:
+        flavor = 'att'
+    build = _vmbuild if _vmSourcesAvailable else 'product'
+    lib = mx.lib_suffix('hsdis-amd64')
+    path = join(_jdk(build), 'jre', 'lib', 'amd64', lib)
+    mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavor + "/" + lib])
+    
 def mx_init():
     _vmbuild = 'product'
     commands = {
         'build': [build, '[-options]'],
         'clean': [clean, ''],
         'copyrightcheck': [copyrightcheck, ''],
+        'hsdis': [hsdis, '[att]'],
         'dacapo': [dacapo, '[[n] benchmark] [VM options|@DaCapo options]'],
-        'specjvm2008': [specjvm2008, ''],
+        'scaladacapo': [scaladacapo, '[[n] benchmark] [VM options|@Scala DaCapo options]'],
+        'specjvm2008': [specjvm2008, '[VM options|@specjvm2008 options]'],
         'example': [example, '[-v] example names...'],
         'gate' : [gate, ''],
         'bench' : [bench, '[-vm vm] [-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'],
--- a/mx/projects	Wed Feb 08 21:13:35 2012 -0800
+++ b/mx/projects	Wed Feb 08 21:15:00 2012 -0800
@@ -41,6 +41,9 @@
 library@DACAPO@path=lib/dacapo-9.12-bach.jar
 library@DACAPO@urls=http://dfn.dl.sourceforge.net/project/dacapobench/9.12-bach/dacapo-9.12-bach.jar
 
+library@DACAPO_SCALA@path=lib/dacapo-scala-0.1.0.jar
+library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20110908.085753-2.jar
+
 # graal.hotspot
 project@com.oracle.max.graal.hotspot@subDir=graal
 project@com.oracle.max.graal.hotspot@sourceDirs=src
@@ -57,6 +60,24 @@
 project@com.oracle.max.graal.debug@sourceDirs=src
 project@com.oracle.max.graal.debug@checkstyle=com.oracle.max.graal.graph
 
+# graal.lir
+project@com.oracle.max.graal.lir@subDir=graal
+project@com.oracle.max.graal.lir@sourceDirs=src
+project@com.oracle.max.graal.lir@dependencies=com.oracle.max.asm,com.oracle.max.graal.nodes
+project@com.oracle.max.graal.lir@checkstyle=com.oracle.max.graal.graph
+
+# graal.lir.amd64
+project@com.oracle.max.graal.lir.amd64@subDir=graal
+project@com.oracle.max.graal.lir.amd64@sourceDirs=src
+project@com.oracle.max.graal.lir.amd64@dependencies=com.oracle.max.graal.lir
+project@com.oracle.max.graal.lir.amd64@checkstyle=com.oracle.max.graal.graph
+
+# graal.alloc
+project@com.oracle.max.graal.alloc@subDir=graal
+project@com.oracle.max.graal.alloc@sourceDirs=src
+project@com.oracle.max.graal.alloc@dependencies=com.oracle.max.graal.lir
+project@com.oracle.max.graal.alloc@checkstyle=com.oracle.max.graal.graph
+
 # graal.snippets
 project@com.oracle.max.graal.snippets@subDir=graal
 project@com.oracle.max.graal.snippets@sourceDirs=src,test
@@ -72,7 +93,7 @@
 # graal.compiler
 project@com.oracle.max.graal.compiler@subDir=graal
 project@com.oracle.max.graal.compiler@sourceDirs=src
-project@com.oracle.max.graal.compiler@dependencies=com.oracle.max.asm,com.oracle.max.graal.nodes
+project@com.oracle.max.graal.compiler@dependencies=com.oracle.max.graal.lir.amd64,com.oracle.max.graal.alloc
 project@com.oracle.max.graal.compiler@checkstyle=com.oracle.max.graal.graph
 
 # graal.java
--- a/mx/sanitycheck.py	Wed Feb 08 21:13:35 2012 -0800
+++ b/mx/sanitycheck.py	Wed Feb 08 21:15:00 2012 -0800
@@ -39,13 +39,28 @@
     'luindex':    [0, 0,  5, 10, 10],
     'lusearch':   [0, 4,  5,  5,  8],
     'pmd':        [0, 0,  5, 10, 13],
-    'sunflow':    [0, 0,  5, 10, 15],
+    'sunflow':    [0, 2,  5, 10, 15],
     'tomcat':     [0, 0,  5, 10, 15],
     'tradebeans': [0, 0,  5, 10, 13],
     'tradesoap':  [2, 4,  5, 10, 15],
     'xalan':      [0, 0,  5, 10, 18],
 }
 
+dacapoScalaSanityWarmup = {
+    'actors':     [0, 0, 2,  8, 10],
+    'apparat':    [0, 0, 1,  2,  3],
+    'factorie':   [0, 0, 2,  5,  5],
+    'kiama':      [0, 0, 3, 13, 15],
+    'scalac':     [0, 0, 5, 15, 20],
+    'scaladoc':   [0, 0, 5, 15, 15],
+    'scalap':     [0, 0, 5, 15, 20],
+    'scalariform':[0, 0, 6, 15, 20],
+    'scalatest':  [0, 0, 2, 10, 12],
+    'scalaxb':    [0, 0, 5, 15, 25],
+    'specs':      [0, 0, 3, 13, 18],
+    'tmt':        [0, 0, 3, 10, 12]
+}
+
 dacapoGateBuildLevels = {
     'avrora':     ['product', 'fastdebug', 'debug'],
     'batik':      ['product', 'fastdebug', 'debug'],
@@ -63,6 +78,21 @@
     'xalan':      ['product', 'fastdebug', 'debug'],
 }
 
+dacapoScalaGateBuildLevels = {
+    'actors':     ['product', 'fastdebug', 'debug'],
+    'apparat':    ['product', 'fastdebug', 'debug'],
+    'factorie':   ['product', 'fastdebug', 'debug'],
+    'kiama':      ['product', 'fastdebug', 'debug'],
+    'scalac':     ['product', 'fastdebug', 'debug'],
+    'scaladoc':   ['product', 'fastdebug', 'debug'],
+    'scalap':     ['product', 'fastdebug', 'debug'],
+    'scalariform':['product', 'fastdebug', 'debug'],
+    'scalatest':  ['product', 'fastdebug', 'debug'],
+    'scalaxb':    ['product', 'fastdebug', 'debug'],
+    'specs':      ['product', 'fastdebug', 'debug'],
+    'tmt':        ['product', 'fastdebug', 'debug'],
+}
+
 class SanityCheckLevel:
     Fast, Gate, Normal, Extensive, Benchmark = range(5)
     
@@ -118,6 +148,36 @@
     
     return Test("DaCapo-" + name, "DaCapo", ['-jar', dacapo, name, '-n', str(n), ] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher], ['-Xms2g', '-XX:MaxPermSize=256m'])
 
+def getScalaDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=[]):
+    checks = []
+    
+    for (bench, ns) in dacapoScalaSanityWarmup.items():
+        if ns[level] > 0:
+            if gateBuildLevel is None or gateBuildLevel in dacapoScalaGateBuildLevels[bench]:
+                checks.append(getScalaDacapo(bench, ns[level], dacapoArgs))
+    
+    return checks
+
+def getScalaDacapo(name, n, dacapoArgs=[]):
+    dacapo = mx.get_env('DACAPO_SCALA_CP')
+    if dacapo is None:
+        l = mx.library('DACAPO_SCALA', False)
+        if l is not None:
+            dacapo = l.get_path(True)
+        else:
+            mx.abort('Scala DaCapo 0.1.0 jar file must be specified with DACAPO_SCALA_CP environment variable or as DACAPO_SCALA library')
+    
+    if not isfile(dacapo) or not dacapo.endswith('.jar'):
+        mx.abort('Specified Scala DaCapo jar file does not exist or is not a jar file: ' + dacapo)
+    
+    dacapoSuccess = re.compile(r"^===== DaCapo 0\.1\.0(-SNAPSHOT)? ([a-zA-Z0-9_]+) PASSED in ([0-9]+) msec =====$")
+    dacapoFail = re.compile(r"^===== DaCapo 0\.1\.0(-SNAPSHOT)? ([a-zA-Z0-9_]+) FAILED (warmup|) =====$")
+    dacapoTime = re.compile(r"===== DaCapo 0\.1\.0(-SNAPSHOT)? (?P<benchmark>[a-zA-Z0-9_]+) PASSED in (?P<time>[0-9]+) msec =====")
+    
+    dacapoMatcher = Matcher(dacapoTime, {'const:name' : 'benchmark', 'const:score' : 'time'})
+    
+    return Test("Scala-DaCapo-" + name, "Scala-DaCapo", ['-jar', dacapo, name, '-n', str(n), ] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher], ['-Xms2g', '-XX:MaxPermSize=256m'])
+
 def getBootstraps():
     time = re.compile(r"Bootstrapping Graal\.+ in (?P<time>[0-9]+) ms")
     scoreMatcher = Matcher(time, {'const:name' : 'const:BootstrapTime', 'const:score' : 'time'})
--- a/mxtool/mx.py	Wed Feb 08 21:13:35 2012 -0800
+++ b/mxtool/mx.py	Wed Feb 08 21:15:00 2012 -0800
@@ -648,6 +648,17 @@
         return name + '.exe'
     return name
 
+def lib_suffix(name):
+    """
+    Gets the platform specific suffix for a library
+    """
+    os = get_os();
+    if os == 'windows':
+        return name + '.dll'
+    if os == 'linux':
+        return name + '.so'
+    return name
+
 """
 A JavaConfig object encapsulates info on how Java commands are run.
 """
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java	Wed Feb 08 21:13:35 2012 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java	Wed Feb 08 21:15:00 2012 -0800
@@ -128,8 +128,8 @@
 
         @Override
         protected Group start() throws SAXException {
-            Group group = new Group(this.getParentObject());
-            
+            final Group group = new Group(this.getParentObject());
+
             String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY);
             Parser.this.differenceEncoding.put(group, (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true"))));
 
@@ -138,12 +138,6 @@
                 monitor.setState(group.getName());
             }
 
-            return group;
-        }
-
-        @Override
-        protected void end(String text) throws SAXException {
-            final Group group = getObject();
             final Folder parent = getParentObject();
             if (groupCallback == null || parent instanceof Group) {
                 SwingUtilities.invokeLater(new Runnable(){
@@ -153,6 +147,12 @@
                     }
                 });
             }
+
+            return group;
+        }
+
+        @Override
+        protected void end(String text) throws SAXException {
         }
     };
     // <method>
@@ -270,7 +270,7 @@
                 graph.addBlockEdge(left, right);
             }
             blockConnections.clear();
-            
+
             SwingUtilities.invokeLater(new Runnable(){
 
                 @Override
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Feb 08 21:13:35 2012 -0800
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Feb 08 21:15:00 2012 -0800
@@ -247,7 +247,7 @@
 }
 
 // public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass);
-JNIEXPORT jobject JNICALL Java_com_oracle_max_graal_hotspot_bridge_CompilerToVMImpl_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) {
+JNIEXPORT jobject JNICALL Java_com_oracle_max_graal_hotspot_bridge_CompilerToVMImpl_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve) {
   TRACE_graal_3("CompilerToVM::RiSignature_lookupType");
   VM_ENTRY_MARK;
   ResourceMark rm;
@@ -282,7 +282,11 @@
         classloader = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->class_loader();
         protectionDomain = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->protection_domain();
       }
-      resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD);
+      if (eagerResolve) {
+        resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD);
+      } else {
+        resolved_type = SystemDictionary::find(nameSymbol, classloader, protectionDomain, THREAD);
+      }
       if (HAS_PENDING_EXCEPTION) {
         CLEAR_PENDING_EXCEPTION;
         resolved_type = NULL;
@@ -943,7 +947,7 @@
   {CC"RiMethod_invocationCount",          CC"("RESOLVED_METHOD")I",                   FN_PTR(RiMethod_1invocationCount)},
   {CC"RiMethod_hasCompiledCode",          CC"("RESOLVED_METHOD")Z",                   FN_PTR(RiMethod_1hasCompiledCode)},
   {CC"RiMethod_getCompiledCodeSize",      CC"("RESOLVED_METHOD")I",                   FN_PTR(RiMethod_1getCompiledCodeSize)},
-  {CC"RiSignature_lookupType",            CC"("STRING RESOLVED_TYPE")"TYPE,           FN_PTR(RiSignature_1lookupType)},
+  {CC"RiSignature_lookupType",            CC"("STRING RESOLVED_TYPE"Z)"TYPE,          FN_PTR(RiSignature_1lookupType)},
   {CC"RiConstantPool_lookupConstant",     CC"("RESOLVED_TYPE"I)"OBJECT,               FN_PTR(RiConstantPool_1lookupConstant)},
   {CC"RiConstantPool_lookupMethod",       CC"("RESOLVED_TYPE"IB)"METHOD,              FN_PTR(RiConstantPool_1lookupMethod)},
   {CC"RiConstantPool_lookupType",         CC"("RESOLVED_TYPE"I)"TYPE,                 FN_PTR(RiConstantPool_1lookupType)},
--- a/src/share/vm/graal/graalVmIds.hpp	Wed Feb 08 21:13:35 2012 -0800
+++ b/src/share/vm/graal/graalVmIds.hpp	Wed Feb 08 21:15:00 2012 -0800
@@ -72,7 +72,7 @@
 }
 
 inline Symbol* VmIds::toSymbol(jstring string) {
-  return java_lang_String::as_symbol_or_null(JNIHandles::resolve(string));
+  return java_lang_String::as_symbol(JNIHandles::resolve(string), Thread::current());
 }
 
 inline jlong VmIds::getBoxedLong(oop obj) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/BatikSVGProxy/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.svg" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.svg.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/BatikSVGProxy/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.svg
+OpenIDE-Module-Layer: com/sun/hotspot/igv/svg/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/svg/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/BatikSVGProxy/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.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>
+    <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/visualizer/BatikSVGProxy/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -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=ebcf0422
+nbproject/build-impl.xml.script.CRC32=42ef3ff6
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/BatikSVGProxy/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/BatikSVGProxy/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,14 @@
+<?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.svg</code-name-base>
+            <suite-component/>
+            <module-dependencies/>
+            <public-packages>
+                <package>com.sun.hotspot.igv.svg</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/BatikSVGProxy/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/BatikSVG.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,102 @@
+/*
+ * 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.svg;
+
+import java.awt.Graphics2D;
+import java.io.Writer;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import org.w3c.dom.DOMImplementation;
+
+/**
+ * Utility class
+ * @author Thomas Wuerthinger
+ */
+public class BatikSVG {
+
+    private BatikSVG() {
+    }
+
+    private static Constructor SVGGraphics2DConstructor;
+    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<?> 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) getDOMImplementationMethod.invoke(null);
+            org.w3c.dom.Document document = dom.createDocument("http://www.w3.org/2000/svg", "svg", null);
+            Object ctx = createDefaultMethod.invoke(null, document);
+            setEmbeddedFontsOnMethod.invoke(ctx, true);
+            Graphics2D svgGenerator = (Graphics2D) SVGGraphics2DConstructor.newInstance(ctx, true);
+            return svgGenerator;
+        } catch (ClassNotFoundException e) {
+            return null;
+        } catch (NoSuchMethodException e) {
+            return null;
+        } catch (IllegalAccessException e) {
+            return null;
+        } catch (InvocationTargetException e) {
+            return null;
+        } catch (InstantiationException 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 {
+            streamMethod.invoke(svgGenerator, stream, useCSS);
+        } catch (IllegalAccessException e) {
+            assert false;
+        } catch (InvocationTargetException e) {
+            assert false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=BatikSVGProxy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/layer.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,4 @@
+<?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/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/package-info.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ *
+ */
+/**
+ * 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;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.bytecodes" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.bytecodes.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.bytecodes-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=1dee290d
+build.xml.script.CRC32=d594034f
+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=1dee290d
+nbproject/build-impl.xml.script.CRC32=b4dab126
+nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.bytecodes</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>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.jdesktop.layout</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.16.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.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.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>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,5 @@
+CTL_BytecodeViewAction=Bytecode
+CTL_BytecodeViewTopComponent=Bytecode
+CTL_SelectBytecodesAction=Select nodes
+HINT_BytecodeViewTopComponent=Shows the bytecode associated with the displayed graph.
+OpenIDE-Module-Name=Bytecodes
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,101 @@
+/*
+ * 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.bytecodes;
+
+import com.sun.hotspot.igv.data.InputBytecode;
+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.Image;
+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.ImageUtilities;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class BytecodeNode extends AbstractNode {
+
+    private Set<InputNode> nodes;
+
+    public BytecodeNode(InputBytecode bytecode, InputGraph graph, String bciValue) {
+
+        super(Children.LEAF);
+        this.setDisplayName(bytecode.getBci() + " " + bytecode.getName());
+
+        bciValue = bytecode.getBci() + " " + bciValue;
+        bciValue = bciValue.trim();
+
+        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 LinkedHashSet<>();
+            for (InputNode n : nodeList) {
+                nodes.add(n);
+            }
+            this.setDisplayName(this.getDisplayName() + " (" + nodes.size() + " nodes)");
+        }
+    }
+
+    @Override
+    public Image getIcon(int i) {
+        if (nodes != null) {
+            return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/link.png");
+        } else {
+            return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/bytecode.png");
+        }
+    }
+
+    @Override
+    public Image getOpenedIcon(int i) {
+        return getIcon(i);
+    }
+
+    @Override
+    public Action[] getActions(boolean b) {
+        return new Action[]{(Action) SelectBytecodesAction.findObject(SelectBytecodesAction.class, true)};
+    }
+
+    @Override
+    public Action getPreferredAction() {
+        return (Action) SelectBytecodesAction.findObject(SelectBytecodesAction.class, true);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends Node.Cookie> T getCookie(Class<T> aClass) {
+        if (aClass == SelectBytecodesCookie.class && nodes != null) {
+            return (T) (new SelectBytecodesCookie(nodes));
+        }
+        return super.getCookie(aClass);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.bytecodes;
+
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import org.openide.util.NbBundle;
+import org.openide.windows.TopComponent;
+
+/**
+ * @author Thomas Wuerthinger
+ */
+public class BytecodeViewAction extends AbstractAction {
+
+    public BytecodeViewAction() {
+        super(NbBundle.getMessage(BytecodeViewAction.class, "CTL_BytecodeViewAction"));
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent evt) {
+        TopComponent win = BytecodeViewTopComponent.findInstance();
+        win.open();
+        win.requestActive();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.form	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <EmptySpace min="0" pref="400" max="32767" attributes="0"/>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <EmptySpace min="0" pref="300" max="32767" attributes="0"/>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+</Form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,195 @@
+/*
+ * 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.bytecodes;
+
+import com.sun.hotspot.igv.data.Group;
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import java.awt.BorderLayout;
+import java.io.Serializable;
+import javax.swing.SwingUtilities;
+import org.openide.ErrorManager;
+import org.openide.explorer.ExplorerManager;
+import org.openide.explorer.ExplorerUtils;
+import org.openide.explorer.view.BeanTreeView;
+import org.openide.util.*;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
+
+/**
+ * @author Thomas Wuerthinger
+ */
+final class BytecodeViewTopComponent extends TopComponent implements ExplorerManager.Provider, LookupListener {
+
+    private static BytecodeViewTopComponent instance;
+    private static final String PREFERRED_ID = "BytecodeViewTopComponent";
+    private ExplorerManager manager;
+    private BeanTreeView treeView;
+    private Lookup.Result result = null;
+    private MethodNode rootNode;
+
+    private BytecodeViewTopComponent() {
+        initComponents();
+        setName(NbBundle.getMessage(BytecodeViewTopComponent.class, "CTL_BytecodeViewTopComponent"));
+        setToolTipText(NbBundle.getMessage(BytecodeViewTopComponent.class, "HINT_BytecodeViewTopComponent"));
+
+        manager = new ExplorerManager();
+        rootNode = new MethodNode(null, null, "");
+        manager.setRootContext(rootNode);
+
+        setLayout(new BorderLayout());
+
+        treeView = new BeanTreeView();
+        treeView.setRootVisible(false);
+        this.add(BorderLayout.CENTER, treeView);
+        associateLookup(ExplorerUtils.createLookup(manager, getActionMap()));
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(0, 400, Short.MAX_VALUE)
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(0, 300, Short.MAX_VALUE)
+        );
+    }// </editor-fold>//GEN-END:initComponents
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    // End of variables declaration//GEN-END:variables
+
+    /**
+     * Gets default instance. Do not use directly: reserved for *.settings files only,
+     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
+     * To obtain the singleton instance, use {@link findInstance}.
+     */
+    public static synchronized BytecodeViewTopComponent getDefault() {
+        if (instance == null) {
+            instance = new BytecodeViewTopComponent();
+        }
+        return instance;
+    }
+
+    /**
+     * Obtain the BytecodeViewTopComponent instance. Never call {@link #getDefault} directly!
+     */
+    public static synchronized BytecodeViewTopComponent findInstance() {
+        TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
+        if (win == null) {
+            ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot find BytecodeView component. It will not be located properly in the window system.");
+            return getDefault();
+        }
+        if (win instanceof BytecodeViewTopComponent) {
+            return (BytecodeViewTopComponent) win;
+        }
+        ErrorManager.getDefault().log(ErrorManager.WARNING, "There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior.");
+        return getDefault();
+    }
+
+    @Override
+    public int getPersistenceType() {
+        return TopComponent.PERSISTENCE_ALWAYS;
+    }
+
+    @Override
+    public void componentOpened() {
+        Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<>(InputGraphProvider.class);
+        result = Utilities.actionsGlobalContext().lookup(tpl);
+        result.addLookupListener(this);
+    }
+
+    @Override
+    public void componentClosed() {
+        result.removeLookupListener(this);
+        result = null;
+    }
+
+    @Override
+    public Object writeReplace() {
+        return new ResolvableHelper();
+    }
+
+    @Override
+    protected String preferredID() {
+        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 = null; // TODO(tw): FIXME //.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
+        if (p != null) {
+            SwingUtilities.invokeLater(new Runnable() {
+                @Override
+                public void run() {
+                    InputGraph graph = p.getGraph();
+                    if (graph != null) {
+                        Group g = graph.getGroup();
+                        rootNode.update(graph, g.getMethod());
+                    }
+                }
+            });
+        }
+    }
+
+    final static class ResolvableHelper implements Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        public Object readResolve() {
+            return BytecodeViewTopComponent.getDefault();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentSettings.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN" "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">
+<settings version="1.0">
+    <module name="com.sun.hotspot.igv.bytecodes" spec="1.0"/>
+    <instanceof class="org.openide.windows.TopComponent"/>
+    <instanceof class="com.sun.hotspot.igv.bytecodes.BytecodeViewTopComponent"/>
+    <instance class="com.sun.hotspot.igv.bytecodes.BytecodeViewTopComponent" method="getDefault"/>
+</settings>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentWstcref.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE tc-ref PUBLIC "-//NetBeans//DTD Top Component in Mode Properties 2.0//EN" "http://www.netbeans.org/dtds/tc-ref2_0.dtd">
+<tc-ref version="2.0" >
+    <module name="com.sun.hotspot.igv.bytecodes" spec="1.0"/>
+    <tc-id id="BytecodeViewTopComponent"/>
+    <state opened="true"/>
+</tc-ref>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/MethodNode.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,101 @@
+/*
+ * 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.bytecodes;
+
+import com.sun.hotspot.igv.data.InputBytecode;
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.InputMethod;
+import java.awt.Image;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+import org.openide.util.ImageUtilities;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class MethodNode extends AbstractNode {
+
+    private static class MethodNodeChildren extends Children.Keys<InputBytecode> {
+
+        private InputMethod method;
+        private InputGraph graph;
+        private String bciString;
+
+        public MethodNodeChildren(InputMethod method, InputGraph graph, String bciString) {
+            this.method = method;
+            this.bciString = bciString;
+            this.graph = graph;
+        }
+
+        @Override
+        protected Node[] createNodes(InputBytecode bc) {
+            if (bc.getInlined() == null) {
+                return new Node[]{new BytecodeNode(bc, graph, bciString)};
+            } else {
+                return new Node[]{new BytecodeNode(bc, graph, bciString), new MethodNode(bc.getInlined(), graph, bc.getBci() + " " + bciString)};
+            }
+        }
+
+        @Override
+        public void addNotify() {
+            if (method != null) {
+                setKeys(method.getBytecodes());
+            }
+        }
+
+        public void setMethod(InputMethod method, InputGraph graph) {
+            this.method = method;
+            this.graph = graph;
+            addNotify();
+        }
+    }
+
+    /** Creates a new instance of MethodNode */
+    public MethodNode(InputMethod method, InputGraph graph, String bciString) {
+        super((method != null && method.getBytecodes().size() == 0) ? Children.LEAF : new MethodNodeChildren(method, graph, bciString));
+        if (method != null) {
+            this.setDisplayName(method.getName());
+        }
+    }
+
+    @Override
+    public Image getIcon(int i) {
+        return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/method.png");
+    }
+
+    @Override
+    public Image getOpenedIcon(int i) {
+        return getIcon(i);
+    }
+
+    public void update(InputGraph graph, InputMethod method) {
+        ((MethodNodeChildren) this.getChildren()).setMethod(method, graph);
+        if (method != null) {
+            this.setDisplayName(method.getName());
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.bytecodes;
+
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+import org.openide.util.actions.CookieAction;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class SelectBytecodesAction extends CookieAction {
+
+    @Override
+    protected void performAction(Node[] activatedNodes) {
+        SelectBytecodesCookie c = activatedNodes[0].getCookie(SelectBytecodesCookie.class);
+        InputGraphProvider p = null; // TODO: fixme 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
+        };
+    }
+
+    @Override
+    protected void initialize() {
+        super.initialize();
+        putValue("noIconInMenu", Boolean.TRUE);
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesCookie.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,47 @@
+/*
+ * 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.bytecodes;
+
+import com.sun.hotspot.igv.data.InputNode;
+import java.util.Collections;
+import java.util.Set;
+import org.openide.nodes.Node;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class SelectBytecodesCookie implements Node.Cookie {
+
+    private Set<InputNode> nodes;
+
+    /** Creates a new instance of SelectBytecodesCookie */
+    public SelectBytecodesCookie(Set<InputNode> nodes) {
+        this.nodes = nodes;
+    }
+
+    public Set<InputNode> getNodes() {
+        return Collections.unmodifiableSet(nodes);
+    }
+}
Binary file visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/bytecode.png has changed
Binary file visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/link.png has changed
Binary file visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/method.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/layer.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
+<filesystem>
+    <folder name="Actions">
+        <folder name="Edit">
+            <file name="com-sun-hotspot-igv-bytecodes-SelectBytecodesAction.instance"/>
+        </folder>
+        <folder name="Window">
+            <file name="com-sun-hotspot-igv-bytecodes-BytecodeViewAction.instance"/>
+        </folder>
+    </folder>
+    <folder name="Menu">
+        <folder name="Window">
+            <file name="BytecodeViewAction.shadow">
+                <attr name="originalFile" stringvalue="Actions/Window/com-sun-hotspot-igv-bytecodes-BytecodeViewAction.instance"/>
+            </file>
+        </folder>
+    </folder>
+    <folder name="Windows2">
+        <folder name="Components">
+            <file name="BytecodeViewTopComponent.settings" url="BytecodeViewTopComponentSettings.xml"/>
+        </folder>
+        <folder name="Modes">
+            <folder name="customRightTopMode">
+                <file name="BytecodeViewTopComponent.wstcref" url="BytecodeViewTopComponentWstcref.xml"/>
+            </folder>
+        </folder>
+    </folder>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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="at.ssw.visualizer.cfg" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project at.ssw.visualizer.cfg.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: at.ssw.visualizer.cfg
+OpenIDE-Module-Layer: at/ssw/visualizer/cfg/layer.xml
+OpenIDE-Module-Localizing-Bundle: at/ssw/visualizer/cfg/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="at.ssw.visualizer.cfg-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/visualizer/ControlFlowEditor/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=d86dea19
+build.xml.script.CRC32=ec651852
+build.xml.stylesheet.CRC32=a56c6a5b@2.47.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=d86dea19
+nbproject/build-impl.xml.script.CRC32=d9cb852b
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,204 @@
+cluster.path=\
+    ${nbplatform.active.dir}/ide:\
+    ${nbplatform.active.dir}/platform
+disabled.modules=\
+    com.jcraft.jsch,\
+    com.jcraft.jzlib,\
+    org.apache.commons.codec,\
+    org.apache.commons.httpclient,\
+    org.apache.commons.io,\
+    org.apache.commons.lang,\
+    org.apache.commons.logging,\
+    org.apache.ws.commons.util,\
+    org.apache.xml.resolver,\
+    org.apache.xmlrpc,\
+    org.eclipse.core.contenttype,\
+    org.eclipse.core.jobs,\
+    org.eclipse.core.net,\
+    org.eclipse.core.runtime,\
+    org.eclipse.core.runtime.compatibility.auth,\
+    org.eclipse.equinox.app,\
+    org.eclipse.equinox.common,\
+    org.eclipse.equinox.preferences,\
+    org.eclipse.equinox.registry,\
+    org.eclipse.equinox.security,\
+    org.eclipse.jgit,\
+    org.eclipse.mylyn.bugzilla.core,\
+    org.eclipse.mylyn.commons.core,\
+    org.eclipse.mylyn.commons.net,\
+    org.eclipse.mylyn.commons.xmlrpc,\
+    org.eclipse.mylyn.tasks.core,\
+    org.mozilla.rhino.patched,\
+    org.netbeans.api.debugger,\
+    org.netbeans.api.java.classpath,\
+    org.netbeans.api.xml,\
+    org.netbeans.core.browser,\
+    org.netbeans.core.execution,\
+    org.netbeans.core.ide,\
+    org.netbeans.core.io.ui,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.nativeaccess,\
+    org.netbeans.core.osgi,\
+    org.netbeans.lib.cvsclient,\
+    org.netbeans.lib.terminalemulator,\
+    org.netbeans.libs.antlr3.runtime,\
+    org.netbeans.libs.bytelist,\
+    org.netbeans.libs.commons_net,\
+    org.netbeans.libs.freemarker,\
+    org.netbeans.libs.git,\
+    org.netbeans.libs.ini4j,\
+    org.netbeans.libs.jaxb,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.junit4,\
+    org.netbeans.libs.jvyamlb,\
+    org.netbeans.libs.lucene,\
+    org.netbeans.libs.smack,\
+    org.netbeans.libs.svnClientAdapter,\
+    org.netbeans.libs.svnClientAdapter.javahl,\
+    org.netbeans.libs.svnClientAdapter.svnkit,\
+    org.netbeans.libs.swingx,\
+    org.netbeans.libs.xerces,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.bugtracking,\
+    org.netbeans.modules.bugtracking.bridge,\
+    org.netbeans.modules.bugzilla,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.csl.api,\
+    org.netbeans.modules.css.editor,\
+    org.netbeans.modules.css.lib,\
+    org.netbeans.modules.css.visual,\
+    org.netbeans.modules.db,\
+    org.netbeans.modules.db.core,\
+    org.netbeans.modules.db.dataview,\
+    org.netbeans.modules.db.drivers,\
+    org.netbeans.modules.db.kit,\
+    org.netbeans.modules.db.metadata.model,\
+    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.derby,\
+    org.netbeans.modules.dlight.nativeexecution,\
+    org.netbeans.modules.dlight.terminal,\
+    org.netbeans.modules.editor.bookmarks,\
+    org.netbeans.modules.editor.bracesmatching,\
+    org.netbeans.modules.editor.codetemplates,\
+    org.netbeans.modules.editor.completion,\
+    org.netbeans.modules.editor.guards,\
+    org.netbeans.modules.editor.indent.project,\
+    org.netbeans.modules.editor.kit,\
+    org.netbeans.modules.editor.macros,\
+    org.netbeans.modules.editor.structure,\
+    org.netbeans.modules.extbrowser,\
+    org.netbeans.modules.extexecution,\
+    org.netbeans.modules.extexecution.destroy,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.git,\
+    org.netbeans.modules.glassfish.common,\
+    org.netbeans.modules.gototest,\
+    org.netbeans.modules.gsf.codecoverage,\
+    org.netbeans.modules.gsf.testrunner,\
+    org.netbeans.modules.html,\
+    org.netbeans.modules.html.editor,\
+    org.netbeans.modules.html.editor.lib,\
+    org.netbeans.modules.html.lexer,\
+    org.netbeans.modules.html.parser,\
+    org.netbeans.modules.html.validation,\
+    org.netbeans.modules.httpserver,\
+    org.netbeans.modules.hudson,\
+    org.netbeans.modules.hudson.git,\
+    org.netbeans.modules.hudson.mercurial,\
+    org.netbeans.modules.hudson.subversion,\
+    org.netbeans.modules.hudson.tasklist,\
+    org.netbeans.modules.ide.kit,\
+    org.netbeans.modules.image,\
+    org.netbeans.modules.javascript.editing,\
+    org.netbeans.modules.javascript.hints,\
+    org.netbeans.modules.javascript.kit,\
+    org.netbeans.modules.javascript.refactoring,\
+    org.netbeans.modules.jellytools.ide,\
+    org.netbeans.modules.jumpto,\
+    org.netbeans.modules.keyring.impl,\
+    org.netbeans.modules.languages,\
+    org.netbeans.modules.languages.diff,\
+    org.netbeans.modules.languages.manifest,\
+    org.netbeans.modules.languages.yaml,\
+    org.netbeans.modules.lexer.nbbridge,\
+    org.netbeans.modules.localhistory,\
+    org.netbeans.modules.mercurial,\
+    org.netbeans.modules.netbinox,\
+    org.netbeans.modules.parsing.api,\
+    org.netbeans.modules.parsing.lucene,\
+    org.netbeans.modules.print.editor,\
+    org.netbeans.modules.project.ant,\
+    org.netbeans.modules.project.libraries,\
+    org.netbeans.modules.projectui,\
+    org.netbeans.modules.projectui.buildmenu,\
+    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.server,\
+    org.netbeans.modules.servletapi,\
+    org.netbeans.modules.spellchecker,\
+    org.netbeans.modules.spellchecker.apimodule,\
+    org.netbeans.modules.spellchecker.bindings.htmlxml,\
+    org.netbeans.modules.spellchecker.bindings.properties,\
+    org.netbeans.modules.spellchecker.dictionary_en,\
+    org.netbeans.modules.spellchecker.kit,\
+    org.netbeans.modules.spi.actions,\
+    org.netbeans.modules.subversion,\
+    org.netbeans.modules.swing.validation,\
+    org.netbeans.modules.target.iterator,\
+    org.netbeans.modules.tasklist.kit,\
+    org.netbeans.modules.tasklist.projectint,\
+    org.netbeans.modules.tasklist.todo,\
+    org.netbeans.modules.tasklist.ui,\
+    org.netbeans.modules.terminal,\
+    org.netbeans.modules.usersguide,\
+    org.netbeans.modules.utilities,\
+    org.netbeans.modules.utilities.project,\
+    org.netbeans.modules.versioning,\
+    org.netbeans.modules.versioning.indexingbridge,\
+    org.netbeans.modules.versioning.system.cvss.installer,\
+    org.netbeans.modules.versioning.util,\
+    org.netbeans.modules.web.client.tools.api,\
+    org.netbeans.modules.web.common,\
+    org.netbeans.modules.web.indent,\
+    org.netbeans.modules.xml,\
+    org.netbeans.modules.xml.axi,\
+    org.netbeans.modules.xml.catalog,\
+    org.netbeans.modules.xml.core,\
+    org.netbeans.modules.xml.jaxb.api,\
+    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.execution,\
+    org.openide.options,\
+    org.openide.util.enumerations
+## 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,\
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,146 @@
+<?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>at.ssw.visualizer.cfg</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.oracle.graal.visualizer.editor</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.oracle.graal.visualizer.sharedactions</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>org.eclipse.draw2d</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>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.visual</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>2.9.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.5</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.40.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.1.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</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.loaders</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.5</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.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.3.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>
+                <package>at.ssw.visualizer.cfg</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+at.ssw.visualizer.cfg.CfgCompilationViewerFactory
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=ControlFlowEditor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgCompilationViewer.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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 at.ssw.visualizer.cfg;
+
+import at.ssw.visualizer.cfg.action.*;
+import at.ssw.visualizer.cfg.graph.CfgScene;
+import at.ssw.visualizer.cfg.graph.EdgeWidget;
+import at.ssw.visualizer.cfg.graph.NodeWidget;
+import at.ssw.visualizer.cfg.model.CfgEdge;
+import at.ssw.visualizer.cfg.model.CfgNode;
+import at.ssw.visualizer.cfg.preferences.CfgPreferences;
+import at.ssw.visualizer.cfg.preferences.FlagsSetting;
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+import com.oracle.graal.visualizer.editor.CompilationViewer;
+import com.sun.hotspot.igv.data.InputGraph;
+import java.awt.Color;
+import java.awt.Component;
+import java.beans.PropertyChangeEvent;
+import javax.swing.*;
+import javax.swing.border.Border;
+import org.netbeans.api.visual.widget.Widget;
+import org.openide.awt.Toolbar;
+import org.openide.util.Lookup;
+import org.openide.util.actions.SystemAction;
+import org.openide.util.lookup.Lookups;
+
+class CfgCompilationViewer implements CompilationViewer {
+
+    private CfgScene scene;
+    private JScrollPane jScrollPane;
+    private ControlFlowGraph cfg;
+    private JComponent myView;
+
+    public CfgCompilationViewer(InputGraph cfg) {
+        this.cfg = cfg;
+
+       // setIcon(ImageUtilities.loadImage("at/ssw/visualizer/cfg/icons/cfg.gif"));
+//        setName(cfg.getParent().getShortName());
+//        setToolTipText(cfg.getCompilation().getMethod() + " - " + cfg.getName());
+        // TODO(tw): Add title.
+
+        //panel setup
+        this.jScrollPane = new JScrollPane();
+        this.jScrollPane.setOpaque(true);
+        this.jScrollPane.setBorder(BorderFactory.createEmptyBorder());
+        this.jScrollPane.setViewportBorder(BorderFactory.createEmptyBorder());
+        this.scene = new CfgScene(jScrollPane, cfg);
+        this.myView = scene.createView();
+        this.jScrollPane.setViewportView(myView);
+        jScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
+        jScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
+        jScrollPane.getVerticalScrollBar().setEnabled(true);
+        jScrollPane.getHorizontalScrollBar().setEnabled(true);
+
+        //setup enviroment,register listeners
+        // TODO(tw): Add to lookup.
+//        selection = new Selection();
+//        selection.put(cfg);
+//        selection.put(scene);
+//        selection.addChangeListener(scene);
+
+        scene.validate();
+        scene.applyLayout();
+    }
+
+    public void propertyChange(PropertyChangeEvent evt) {
+        if (this.scene != null) {
+
+            String propName = evt.getPropertyName();
+            CfgPreferences prefs = CfgPreferences.getInstance();
+            switch (propName) {
+                case CfgPreferences.PROP_BACKGROUND_COLOR:
+                    scene.setBackground(prefs.getBackgroundColor());
+                    scene.revalidate();
+                    break;
+                case CfgPreferences.PROP_NODE_COLOR:
+                    for (NodeWidget nw : scene.getNodeWidgets()) {
+                        //only change the node color if its not a custom color
+                        if (!nw.isNodeColorCustomized()) {
+                            nw.setNodeColor(prefs.getNodeColor(), false);
+                        }
+                    }
+                    break;
+                case CfgPreferences.PROP_EDGE_COLOR:
+                    for (CfgEdge e : scene.getEdges()) {
+                        if (!e.isBackEdge() && !e.isXhandler()) {
+                            EdgeWidget w = (EdgeWidget) scene.findWidget(e);
+                            w.setLineColor(prefs.getEdgeColor());
+                        }
+                    }
+                    break;
+                case CfgPreferences.PROP_BACK_EDGE_COLOR:
+                    for (CfgEdge e : scene.getEdges()) {
+                        if (e.isBackEdge()) {
+                            EdgeWidget w = (EdgeWidget) scene.findWidget(e);
+                            w.setLineColor(prefs.getBackedgeColor());
+                        }
+                    }
+                    break;
+                case CfgPreferences.PROP_EXCEPTION_EDGE_COLOR:
+                    for (CfgEdge e : scene.getEdges()) {
+                        if (e.isXhandler()) {
+                            EdgeWidget w = (EdgeWidget) scene.findWidget(e);
+                            w.setLineColor(prefs.getExceptionEdgeColor());
+                        }
+                    }
+                    break;
+                case CfgPreferences.PROP_BORDER_COLOR:
+                    for (CfgNode n : scene.getNodes()) {
+                        NodeWidget nw = (NodeWidget) scene.findWidget(n);
+                        nw.setBorderColor(prefs.getBorderColor());
+                    }
+                    break;
+                case CfgPreferences.PROP_TEXT_FONT:
+                    for (CfgNode n : scene.getNodes()) {
+                        NodeWidget nw = (NodeWidget) scene.findWidget(n);
+                        nw.adjustFont(prefs.getTextFont());
+                    }
+                    break;
+                case CfgPreferences.PROP_TEXT_COLOR:
+                    for (CfgNode n : scene.getNodes()) {
+                        NodeWidget nw = (NodeWidget) scene.findWidget(n);
+                        nw.setForeground(prefs.getTextColor());
+                    }
+                    break;
+                case CfgPreferences.PROP_FLAGS:
+                    FlagsSetting fs = CfgPreferences.getInstance().getFlagsSetting();
+                    for (CfgNode n : scene.getNodes()) {
+                        NodeWidget nw = (NodeWidget) scene.findWidget(n);
+                        Color nodeColor = fs.getColor(n.getBasicBlock().getFlags());
+                        if (nodeColor != null) {
+                            nw.setNodeColor(nodeColor, true);
+                        } else {
+                            nw.setNodeColor(CfgPreferences.getInstance().getNodeColor(), false);
+                        }
+                    }
+                    break;
+                case CfgPreferences.PROP_SELECTION_COLOR_BG:
+                case CfgPreferences.PROP_SELECTION_COLOR_FG:
+                    for (CfgNode n : scene.getNodes()) {
+                        Widget w = scene.findWidget(n);
+                        w.revalidate();
+                    }
+                    break;
+            }
+            scene.validate();
+        }
+
+    }
+
+    /*@Override
+    public Component getToolBarComponent() {
+        Toolbar tb = new Toolbar("CfgToolbar");
+
+        tb.setBorder((Border) UIManager.get("Nb.Editor.Toolbar.border"));
+
+        //zoomin/zoomout buttons
+        tb.add(SystemAction.get(ZoominAction.class).getToolbarPresenter());
+        tb.add(SystemAction.get(ZoomoutAction.class).getToolbarPresenter());
+        tb.addSeparator();
+
+        //router buttons
+        ButtonGroup routerButtons = new ButtonGroup();
+        UseDirectLineRouterAction direct = SystemAction.get(UseDirectLineRouterAction.class);
+        UseBezierRouterAction bezier = SystemAction.get(UseBezierRouterAction.class);
+        JToggleButton button = (JToggleButton) direct.getToolbarPresenter();
+        button.getModel().setGroup(routerButtons);
+        button.setSelected(true);
+        tb.add(button);
+        button = (JToggleButton) bezier.getToolbarPresenter();
+        button.getModel().setGroup(routerButtons);
+        tb.add(button);
+        tb.addSeparator();
+
+        //layout buttons
+        tb.add(SystemAction.get(HierarchicalNodeLayoutAction.class).getToolbarPresenter());
+        tb.add(SystemAction.get(HierarchicalCompoundLayoutAction.class).getToolbarPresenter());
+
+        tb.addSeparator();
+        tb.add(SystemAction.get(ShowAllAction.class).getToolbarPresenter());
+        tb.addSeparator();
+
+        //cluster button
+        tb.add(SystemAction.get(SwitchLoopClustersAction.class).getToolbarPresenter());
+        tb.addSeparator();
+
+        //show/hide edge button
+        tb.add(SystemAction.get(ShowEdgesAction.class).getToolbarPresenter());
+        tb.add(SystemAction.get(HideEdgesAction.class).getToolbarPresenter());
+        tb.addSeparator();
+
+        //color button       
+        JComponent colorButton = SystemAction.get(ColorAction.class).getToolbarPresenter();
+        scene.addCfgEventListener((CfgEventListener) colorButton);
+        tb.add(colorButton);
+
+        //export button           
+        tb.add(SystemAction.get(ExportAction.class).getToolbarPresenter());
+        tb.doLayout();
+
+        return tb;
+    }*/
+
+    @Override
+    public Lookup getLookup() {
+        return Lookups.fixed(scene);
+    }
+
+    @Override
+    public Component getComponent() {
+        return jScrollPane;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgCompilationViewerFactory.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,26 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package at.ssw.visualizer.cfg;
+
+import com.oracle.graal.visualizer.editor.CompilationViewer;
+import com.oracle.graal.visualizer.editor.CompilationViewerFactory;
+import com.oracle.graal.visualizer.editor.DiagramViewModel;
+import com.oracle.graal.visualizer.editor.SplitCompilationViewerFactory;
+import com.sun.hotspot.igv.data.InputGraph;
+
+public class CfgCompilationViewerFactory extends SplitCompilationViewerFactory {
+
+    @Override
+    public String getName() {
+        return "CFG";
+    }
+
+    @Override
+    protected CompilationViewer createViewer(InputGraph graph) {
+        return new CfgCompilationViewer(graph);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgEditorContext.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,10 @@
+
+package at.ssw.visualizer.cfg;
+
+public abstract class CfgEditorContext {
+      
+    public static final int LAYOUT_HIERARCHICALNODELAYOUT = 1;
+    public static final int LAYOUT_HIERARCHICALCOMPOUNDLAYOUT = 2;
+       
+    public static final int MAX_AUTOEDGESVISIBLE = 8;            
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/AbstractCfgEditorAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,57 @@
+package at.ssw.visualizer.cfg.action;
+
+
+import at.ssw.visualizer.cfg.graph.CfgScene;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JMenuItem;
+import org.openide.util.Utilities;
+import org.openide.util.actions.CallableSystemAction;
+
+/**
+ * The common superclass of all concrete actions related to the CFG visualizer.
+ *
+ * @author Bernhard Stiftner
+ * @author Rumpfhuber Stefan
+ */
+public abstract class AbstractCfgEditorAction extends CallableSystemAction {
+
+    CfgScene topComponent = null;
+    
+    public AbstractCfgEditorAction() {        
+        setEnabled(false);
+
+    }
+       
+    protected CfgScene getEditor() {
+        return Utilities.actionsGlobalContext().lookup(CfgScene.class);
+    }
+    
+    @Override
+    public JMenuItem getMenuPresenter() {
+        return new JMenuItem(this);
+    }
+
+   
+    @Override
+    public JComponent getToolbarPresenter() {
+        JButton b = new JButton(this);
+        if (getIcon() != null) {
+            b.setText(null);
+            b.setToolTipText(getName());
+        }
+        return b;
+    }
+
+   
+    @Override
+    public JMenuItem getPopupPresenter() {       
+        return new JMenuItem(this);
+    }
+    
+   
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+CTL_SomeAction=test
+CTL_SomeAction2=test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HideEdgesAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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 at.ssw.visualizer.cfg.action;
+
+
+import at.ssw.visualizer.cfg.graph.CfgScene;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+
+@ActionID(id = "at.ssw.visualizer.cfg.action.HideEdges", category = "View")
+@ActionRegistration(displayName = "Hide Edges", iconBase="at/ssw/visualizer/cfg/icons/hideedges.gif")
+@ActionReference(path = "CompilationViewer/CFG/Actions", position = 180)
+public class HideEdgesAction implements ActionListener {
+
+    private List<CfgScene> scenes;
+    
+    public HideEdgesAction(List<CfgScene> scenes) {
+        this.scenes = scenes;
+    }
+    
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        for (CfgScene scene : scenes) {
+             scene.setSelectedEdgesVisibility(false);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalCompoundLayoutAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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 at.ssw.visualizer.cfg.action;
+
+import at.ssw.visualizer.cfg.CfgEditorContext;
+import at.ssw.visualizer.cfg.graph.CfgScene;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+
+
+@ActionID(id = "at.ssw.visualizer.cfg.action.HierarchicalCompoundLayout", category = "View")
+@ActionRegistration(displayName = "Compound Layout", iconBase="at/ssw/visualizer/cfg/icons/arrangeloop.gif")
+@ActionReference(path = "CompilationViewer/CFG/Actions", position = 150)
+public class HierarchicalCompoundLayoutAction implements ActionListener {
+    List<CfgScene> scenes;
+    
+    public HierarchicalCompoundLayoutAction(List<CfgScene> scenes) {
+        this.scenes = scenes;
+    }
+    
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        for (CfgScene s : scenes) {
+            s.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALCOMPOUNDLAYOUT);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalNodeLayoutAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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 at.ssw.visualizer.cfg.action;
+
+import at.ssw.visualizer.cfg.CfgEditorContext;
+import at.ssw.visualizer.cfg.graph.CfgScene;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+
+
+@ActionID(id = "at.ssw.visualizer.cfg.action.HierarchicalNodeLayout", category = "View")
+@ActionRegistration(displayName = "Layout", iconBase="at/ssw/visualizer/cfg/icons/arrangehier.gif")
+@ActionReference(path = "CompilationViewer/CFG/Actions", position = 160)
+public class HierarchicalNodeLayoutAction implements ActionListener {
+    List<CfgScene> scenes;
+    
+    public HierarchicalNodeLayoutAction(List<CfgScene> scenes) {
+        this.scenes = scenes;
+    }
+    
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        for (CfgScene s : scenes) {
+            s.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ShowEdgesAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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 at.ssw.visualizer.cfg.action;
+
+import at.ssw.visualizer.cfg.graph.CfgScene;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+
+
+@ActionID(id = "ShowEdges", category = "View")
+@ActionRegistration(displayName = "Show Edges", iconBase="at/ssw/visualizer/cfg/icons/showedges.gif")
+@ActionReference(path = "CompilationViewer/CFG/Actions", position = 170)
+public class ShowEdgesAction implements ActionListener {
+
+    private List<CfgScene> scenes;
+    
+    public ShowEdgesAction(List<CfgScene> scenes) {
+        this.scenes = scenes;
+    }
+    
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        for (CfgScene scene : scenes) {
+             scene.setSelectedEdgesVisibility(true);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/CfgScene.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,836 @@
+package at.ssw.visualizer.cfg.graph;
+
+import at.ssw.visualizer.cfg.model.CfgEdge;
+import at.ssw.visualizer.cfg.CfgEditorContext;
+import at.ssw.visualizer.cfg.action.HideEdgesAction;
+import at.ssw.visualizer.cfg.action.ShowEdgesAction;
+import at.ssw.visualizer.cfg.graph.layout.HierarchicalCompoundLayout;
+import at.ssw.visualizer.cfg.graph.layout.HierarchicalNodeLayout;
+import at.ssw.visualizer.cfg.model.CfgEnv;
+import at.ssw.visualizer.cfg.model.CfgNode;
+import at.ssw.visualizer.cfg.model.LoopInfo;
+import at.ssw.visualizer.cfg.preferences.CfgPreferences;
+import at.ssw.visualizer.cfg.visual.PolylineRouter;
+import at.ssw.visualizer.cfg.visual.PolylineRouterV2;
+import at.ssw.visualizer.cfg.visual.WidgetCollisionCollector;
+import at.ssw.visualizer.model.cfg.BasicBlock;
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+import com.oracle.graal.visualizer.sharedactions.ZoomCookie;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.event.ActionEvent;
+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.prefs.PreferenceChangeEvent;
+import java.util.prefs.PreferenceChangeListener;
+import java.util.prefs.Preferences;
+import javax.swing.AbstractAction;
+import javax.swing.JComponent;
+import javax.swing.JMenu;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.EventListenerList;
+import org.netbeans.api.visual.action.ActionFactory;
+import org.netbeans.api.visual.action.MoveProvider;
+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.WidgetAction;
+import org.netbeans.api.visual.anchor.Anchor;
+import org.netbeans.api.visual.anchor.AnchorFactory;
+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.router.Router;
+import org.netbeans.api.visual.router.Router.*;
+import org.netbeans.api.visual.router.RouterFactory;
+import org.netbeans.api.visual.widget.ConnectionWidget;
+import org.netbeans.api.visual.widget.LayerWidget;
+import org.netbeans.api.visual.widget.Widget;
+import org.openide.util.NbPreferences;
+import org.openide.util.actions.SystemAction;
+
+public final class CfgScene extends GraphScene<CfgNode, CfgEdge> implements ChangeListener, ZoomCookie {
+
+    private LayerWidget mainLayer = new LayerWidget(this);
+    private LayerWidget connectionLayer = new LayerWidget(this);
+    private LayerWidget interractionLayer = new LayerWidget(this);
+    private LayerWidget clusterLayer = new LayerWidget(this);
+    private Set<CfgNode> selectedNodes = Collections.<CfgNode>emptySet();
+    private Map<Integer, LoopClusterWidget> loopidx2clusterwidget = new HashMap<>();
+    private Map<CfgNode, EdgeSwitchWidget> inputSwitches = new HashMap<>();
+    private Map<CfgNode, EdgeSwitchWidget> outputSwitches = new HashMap<>();
+    private WidgetAction moveAction = ActionFactory.createMoveAction(ActionFactory.createFreeMoveStrategy(), this.createMoveProvider());
+    private SceneLayout sceneLayout;
+    private CfgEnv env;
+    private int currentLayout = -1;
+    private JScrollPane scrollPane;
+    private WidgetAction contextPopupAction = this.createContextMenuAction(this);
+    private List<NodeWidget> nodeWidgets = null;
+    private boolean loopClustersVisible = true;
+    private static String PREFERENCE_LOOP_CLUSTER = "loopClusters";
+    private static String PREFERENCE_ROUTER = "router";
+    private static String PREFERENCE_LAYOUT = "layout";
+
+    public static Preferences getPreferences() {
+        return NbPreferences.forModule(CfgScene.class);
+    }
+    private final PreferenceChangeListener preferenceChangeListener = new PreferenceChangeListener() {
+        @Override
+        public void preferenceChange(PreferenceChangeEvent evt) {
+            if (evt.getKey().equals(PREFERENCE_ROUTER)) {
+                setUseBezierRouter(Boolean.parseBoolean(evt.getNewValue()));
+            } else if (evt.getKey().equals(PREFERENCE_LOOP_CLUSTER)) {
+                setLoopWidgets(Boolean.parseBoolean(evt.getNewValue()));
+            }
+        }
+    };
+
+    public CfgScene(final JScrollPane scrollPane, final ControlFlowGraph cfg) {
+        addChild(clusterLayer);
+        addChild(mainLayer);
+        addChild(interractionLayer);
+        addChild(connectionLayer);
+        this.scrollPane = scrollPane;
+        this.loadModel(new CfgEnv(cfg));
+        this.getInputBindings().setZoomActionModifiers(0);
+        this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1));
+        this.getActions().addAction(ActionFactory.createPanAction());
+        this.getActions().addAction(ActionFactory.createRectangularSelectAction(
+                this.createSelectDecorator(this),
+                interractionLayer,
+                this.createRectangularSelectProvider()));
+        this.getActions().addAction(this.contextPopupAction);
+        this.addSceneListener(createSceneListener(this));
+        this.validate();
+
+        getPreferences().addPreferenceChangeListener(preferenceChangeListener);
+        this.loadDefaults();
+    }
+
+    private void loadModel(CfgEnv cfgenv) {
+        this.env = cfgenv;
+        for (CfgNode n : env.getNodes()) {
+            addNode(n);
+        }
+        for (CfgEdge e : env.getEdges()) {
+            addEdge(e);
+            setEdgeSource(e, e.getSourceNode());
+            setEdgeTarget(e, e.getTargetNode());
+        }
+        this.stackLoops(cfgenv.getLoopMap());
+        this.autoHideEdges();
+    }
+
+    public void loadDefaults() {
+        CfgPreferences prefs = CfgPreferences.getInstance();
+        this.setBackground(prefs.getBackgroundColor());
+        setUseBezierRouter(getPreferences().getBoolean(PREFERENCE_ROUTER, true));
+        setLoopWidgets(getPreferences().getBoolean(PREFERENCE_LOOP_CLUSTER, true));
+        setSceneLayout(getPreferences().getInt(PREFERENCE_LAYOUT, CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT));
+    }
+
+    //sets the parent Widget of all LoopClusterWidgets
+    private void stackLoops(Map<CfgNode, LoopInfo> map) {
+        this.clusterLayer.removeChildren();
+
+        Set<LoopInfo> cache = new HashSet<>();
+        for (LoopInfo info : map.values()) {
+            if (cache.contains(info)) {
+                continue;
+            }
+            LoopClusterWidget widget = this.loopidx2clusterwidget.get(info.getLoopIndex());
+            LoopInfo parent = info.getParent();
+            while (parent != null) {
+                LoopClusterWidget parentWidget = this.loopidx2clusterwidget.get(parent.getLoopIndex());
+                assert parentWidget != null;
+                if (widget.getParentWidget() != null) {
+                    widget.removeFromParent();
+                }
+                parentWidget.addChild(widget);
+                widget = parentWidget;
+                parent = parent.getParent();
+            }
+            widget.removeFromParent();
+            this.clusterLayer.addChild(widget);//parent == null => parent is clusterlayer
+        }
+    }
+
+    //hide in|output edges 
+    private void autoHideEdges() {
+        for (CfgNode n : this.getNodes()) {
+            int fanin = n.getInputEdges().length;
+            int fanout = n.getOutputEdges().length;
+            if (fanin > CfgEditorContext.MAX_AUTOEDGESVISIBLE) {
+                assert (inputSwitches.containsKey(n));
+                if (this.inputSwitches.containsKey(n)) {
+                    EdgeSwitchWidget esw = this.inputSwitches.get(n);
+                    esw.changeEdgeVisibility(false);
+                }
+            }
+            if (fanout > CfgEditorContext.MAX_AUTOEDGESVISIBLE) {
+                if (this.outputSwitches.containsKey(n)) {
+                    EdgeSwitchWidget esw = this.outputSwitches.get(n);
+                    esw.changeEdgeVisibility(false);
+                }
+            }
+        }
+
+    }
+
+    //apply current cfggraphscene layout  
+    public void applyLayout() {
+        this.sceneLayout.invokeLayoutImmediately();
+    }
+
+    //returns a Set with the currently selected Nodes    
+    public Set<CfgNode> getSelectedNodes() {
+        return Collections.<CfgNode>unmodifiableSet(selectedNodes);
+    }
+
+    public Map<Integer, LoopClusterWidget> getLoopidx2clusterwidget() {
+        return loopidx2clusterwidget;
+    }
+
+    /**
+     * Sets the color of the currently selected Nodes If the supplied color is null the default color will be used
+     */
+    public void setSelectedNodesColor(Color color) {
+        if (color == null) { //set default color
+            CfgPreferences prefs = CfgPreferences.getInstance();
+            boolean customized = false;
+            for (CfgNode n : this.selectedNodes) {
+                color = null;
+                color = prefs.getFlagsSetting().getColor(n.getBasicBlock().getFlags());
+                customized = (color != null);
+                NodeWidget nw = (NodeWidget) this.findWidget(n);
+                nw.setNodeColor((customized) ? color : prefs.getNodeColor(), customized);
+            }
+        } else {
+            for (CfgNode n : this.selectedNodes) {
+                NodeWidget nw = (NodeWidget) this.findWidget(n);
+                nw.setNodeColor(color, true);
+            }
+        }
+        this.validate();
+    }
+
+    public void setSelectedEdgesVisibility(boolean visible) {
+        for (CfgNode n : this.selectedNodes) {
+            EdgeSwitchWidget in = this.inputSwitches.get(n);
+            EdgeSwitchWidget out = this.outputSwitches.get(n);
+            if (in != null) {
+                in.changeEdgeVisibility(visible);
+            }
+            if (out != null) {
+                out.changeEdgeVisibility(visible);
+            }
+        }
+        this.validate();
+    }
+
+    public EdgeSwitchWidget getInputSwitch(CfgNode n) {
+        return this.inputSwitches.get(n);
+    }
+
+    public EdgeSwitchWidget getOutputSwitch(CfgNode n) {
+        return this.outputSwitches.get(n);
+    }
+
+    public CfgEnv getCfgEnv() {
+        return env;
+    }
+
+    public boolean isLoopClusterVisible() {
+        return loopClustersVisible;
+    }
+
+    public void setLoopWidgets(boolean visible) {
+        for (Widget w : this.loopidx2clusterwidget.values()) {
+            w.setVisible(visible);
+            w.revalidate();
+        }
+        this.loopClustersVisible = visible;
+        this.validate();
+        getPreferences().putBoolean(PREFERENCE_LOOP_CLUSTER, visible);
+    }
+    
+    private void setUseBezierRouter(boolean value) {
+        Router router;
+        if (value) {
+            router = new PolylineRouterV2(new WidgetCollisionCollector() {
+                @Override
+                public void collectCollisions(List<Widget> collisions) {
+                    collisions.addAll(getNodeWidgets());
+                }
+            });
+        } else {
+            router = RouterFactory.createDirectRouter();
+        }
+
+        for (CfgEdge e : this.getEdges()) {
+            EdgeWidget ew = (EdgeWidget) this.findWidget(e);
+            ew.setRouter(router);
+        }
+        this.validate();
+        getPreferences().putBoolean(PREFERENCE_ROUTER, value);
+    }
+
+    public Collection<NodeWidget> getNodeWidgets() {
+        if (nodeWidgets != null && nodeWidgets.size() == this.getNodes().size()) {
+            return nodeWidgets;
+        }
+
+        List<NodeWidget> widgets = new ArrayList<>();
+        for (CfgNode n : this.getNodes()) {
+            NodeWidget w = (NodeWidget) this.findWidget(n);
+            widgets.add(w);
+        }
+
+        nodeWidgets = Collections.unmodifiableList(widgets);
+        return widgets;
+    }
+
+    public void setSceneLayout(int newLayout) {
+
+        GraphLayout<CfgNode, CfgEdge> graphLayout = null;
+
+        switch (newLayout) {
+            case CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT:
+                graphLayout = new HierarchicalNodeLayout(this);
+                break;
+
+            case CfgEditorContext.LAYOUT_HIERARCHICALCOMPOUNDLAYOUT:
+                graphLayout = new HierarchicalCompoundLayout(this);
+                break;
+        }
+
+        this.currentLayout = newLayout;
+        if (graphLayout != null) {
+            this.sceneLayout = LayoutFactory.createSceneGraphLayout(this, graphLayout);
+        }
+        
+        getPreferences().putInt(PREFERENCE_LAYOUT, newLayout);
+        sceneLayout.invokeLayoutImmediately();
+    }
+
+    @Override
+    protected void attachEdgeSourceAnchor(CfgEdge edge, CfgNode oldSourceNode, CfgNode sourceNode) {
+        Anchor sourceAnchor;
+        EdgeWidget edgeWidget = (EdgeWidget) findWidget(edge);
+        Widget sourceWidget = findWidget(sourceNode);
+
+        if (edge.isSymmetric()) {
+            sourceAnchor = new SymmetricAnchor(sourceWidget, true, true);
+        } else {
+            sourceAnchor = AnchorFactory.createRectangularAnchor(sourceWidget);
+        }
+        edgeWidget.setSourceAnchor(sourceAnchor);
+    }
+
+    @Override
+    protected void attachEdgeTargetAnchor(CfgEdge edge, CfgNode oldtarget, CfgNode targetNode) {
+        Anchor targetAnchor;
+        ConnectionWidget edgeWidget = (ConnectionWidget) findWidget(edge);
+        Widget targetWidget = findWidget(targetNode);
+
+        if (edge.isSymmetric()) {
+            targetAnchor = new SymmetricAnchor(targetWidget, true, false);
+        } else {
+            targetAnchor = AnchorFactory.createRectangularAnchor(targetWidget);
+        }
+        edgeWidget.setTargetAnchor(targetAnchor);
+    }
+
+    @Override
+    protected Widget attachEdgeWidget(CfgEdge edge) {
+        EdgeWidget widget = new EdgeWidget(this, edge);
+        connectionLayer.addChild(widget);
+        attachSourceSwitchWidget(edge);
+        attachTargetSwitchWidget(edge);
+        return widget;
+    }
+
+    @Override
+    protected Widget attachNodeWidget(CfgNode node) {
+        this.nodeWidgets = null;
+
+        NodeWidget nw = new NodeWidget(this, node);
+        WidgetAction.Chain actions = nw.getActions();
+        actions.addAction(this.contextPopupAction);
+        actions.addAction(this.moveAction);
+        actions.addAction(this.createObjectHoverAction());
+
+        if (node.isLoopMember()) {
+            LoopClusterWidget loopWidget = this.attachLoopMember(node);
+            loopWidget.addMember(nw);
+        }
+        mainLayer.addChild(nw);
+        return nw;
+    }
+
+    private LoopClusterWidget attachLoopMember(CfgNode node) {
+        LoopClusterWidget lw = this.loopidx2clusterwidget.get(node.getLoopIndex());
+        if (lw == null) {
+            lw = new LoopClusterWidget(this, node.getLoopDepth(), node.getLoopIndex());
+            this.loopidx2clusterwidget.put(node.getLoopIndex(), lw);
+            this.clusterLayer.addChild(lw);
+        }
+        return lw;
+    }
+
+    private boolean detachLoopMember(CfgNode node, NodeWidget nodeWidget) {
+        LoopClusterWidget rm = this.loopidx2clusterwidget.get(node.getLoopIndex());
+        if (rm == null) {
+            return false;//not added
+        }
+        if (rm.removeMember(nodeWidget)) {
+            if (rm.getMembers().isEmpty()) {
+                this.loopidx2clusterwidget.remove(rm.getLoopIndex());
+                List<Widget> childs = new ArrayList<>(rm.getChildren());
+                for (Widget w : childs) {//append stacked loopwidgets
+                    w.removeFromParent();
+                    rm.getParentWidget().addChild(w);
+                }
+                rm.removeFromParent();
+            }
+            return true;
+        }
+        return false;
+    }
+
+    //this function is not invoked by any class  of the module
+    //however to ensure that the edge switches are treatet corretly
+    //when a future version removes nodes it was implemented too.
+    @Override
+    protected void detachNodeWidget(CfgNode node, Widget nodeWidget) {
+        if (node.isLoopMember() && nodeWidget instanceof NodeWidget) {
+            this.detachLoopMember(node, (NodeWidget) nodeWidget);
+        }
+        super.detachNodeWidget(node, nodeWidget);
+        assert nodeWidget.getParentWidget() == null;
+        if (this.inputSwitches.containsKey(node)) {
+            EdgeSwitchWidget esw = this.inputSwitches.remove(node);
+            this.connectionLayer.removeChild(esw);
+        }
+        if (this.outputSwitches.containsKey(node)) {
+            EdgeSwitchWidget esw = this.outputSwitches.remove(node);
+            this.connectionLayer.removeChild(esw);
+        }
+    }
+
+    protected EdgeSwitchWidget attachSourceSwitchWidget(CfgEdge e) {
+        CfgNode sourceNode = e.getSourceNode();
+        NodeWidget sourceWidget = (NodeWidget) this.findWidget(sourceNode);
+        EdgeSwitchWidget out = outputSwitches.get(sourceNode);
+        if (out == null) {
+            out = new EdgeSwitchWidget(this, sourceWidget, true);
+            this.connectionLayer.addChild(out);
+            outputSwitches.put(sourceNode, out);
+        }
+        return out;
+    }
+
+    protected EdgeSwitchWidget attachTargetSwitchWidget(CfgEdge e) {
+        CfgNode targetNode = e.getTargetNode();
+        NodeWidget targetWidget = (NodeWidget) this.findWidget(targetNode);
+        EdgeSwitchWidget in = inputSwitches.get(targetNode);
+        if (in == null) {
+            in = new EdgeSwitchWidget(this, targetWidget, false);
+            this.connectionLayer.addChild(in);
+            inputSwitches.put(targetNode, in);
+        }
+        return in;
+    }
+
+    //resets the selection state of all NodeWidgets
+    private void cleanNodeSelection() {
+        if (!this.selectedNodes.isEmpty()) {
+            this.userSelectionSuggested(Collections.<CfgNode>emptySet(), false);
+            this.selectedNodes = Collections.<CfgNode>emptySet();
+            this.validate();
+        }
+    }
+
+    //sets the scene & global node selection
+    public void setNodeSelection(Set<CfgNode> newSelection) {
+        this.setSceneSelection(newSelection);
+        this.updateGlobalSelection();
+    }
+
+    //sets the scene selection
+    private void setSceneSelection(Set<CfgNode> newSelection) {
+        if (newSelection.equals(selectedNodes)) {
+            return;
+        }
+
+        this.selectedNodes = newSelection;
+
+        Set<Object> selectedObjects = new HashSet<>();
+
+        for (CfgNode n : newSelection) {
+            selectedObjects.addAll(this.findNodeEdges(n, true, true));
+        }
+        selectedObjects.addAll(newSelection);
+
+        //if the selection gets updated from a change in the block view
+        //the scene will be centered
+        if (selectionUpdating) {
+            this.centerSelection();
+        }
+
+        this.userSelectionSuggested(selectedObjects, false);
+        this.validate();
+    }
+
+    //updates selection of Block View
+    public void updateGlobalSelection() {
+        // TODO(tw): Add selection management.
+//        Selection selection = SelectionManager.getDefault().getCurSelection();
+//        ArrayList<BasicBlock> newBlocks = new ArrayList<BasicBlock>();
+//        for (CfgNode n : this.selectedNodes) {
+//            newBlocks.add(n.getBasicBlock());
+//        }
+//        BasicBlock[] curBlocks = newBlocks.toArray(new BasicBlock[newBlocks.size()]);     
+//        selection.put(curBlocks);
+    }
+    private boolean selectionUpdating = false;
+
+    //change of blockview selection   
+    public void stateChanged(ChangeEvent event) {
+        if (selectionUpdating) {
+            return;
+        }
+
+        selectionUpdating = true;
+
+        Object source = event.getSource();
+//        if(source instanceof Selection){
+//            Selection selection=(Selection) source;
+//            Set<CfgNode> newSelection = new HashSet<CfgNode>();
+//            BasicBlock[] newBlocks = selection.get(BasicBlock[].class);                  
+//            if (newBlocks != null) {
+//                for(BasicBlock b : newBlocks){
+//                    for(CfgNode n : this.getNodes()){
+//                        if(n.getBasicBlock() == b) newSelection.add(n);
+//                    }
+//                }
+//                this.setSceneSelection(newSelection);                               
+//            } 
+//        }       
+        selectionUpdating = false;
+        // TODO(tw): Add selection management.
+    }
+
+    //centers the viewport on the currently selected nodewidgets
+    private void centerSelection() {
+        Point sceneCenter = null;
+        Collection<CfgNode> nodes = this.selectedNodes;
+        if (nodes.size() == 0) {
+            nodes = this.getNodes();
+        }
+
+        for (CfgNode n : nodes) {
+            if (sceneCenter == null) {
+                sceneCenter = this.findWidget(n).getLocation();
+                continue;
+            }
+            Point location = this.findWidget(n).getLocation();
+            sceneCenter.x = (location.x + sceneCenter.x) / 2;
+            sceneCenter.y = (location.y + sceneCenter.y) / 2;
+        }
+
+        JComponent view = this.getView();
+        if (view != null) {
+            Rectangle viewBounds = view.getVisibleRect();
+
+            Point viewCenter = this.convertSceneToView(sceneCenter);
+
+            view.scrollRectToVisible(new Rectangle(
+                    viewCenter.x - viewBounds.width / 2,
+                    viewCenter.y - viewBounds.height / 2,
+                    viewBounds.width,
+                    viewBounds.height));
+        }
+    }
+
+    public void zoomScene() {
+        JScrollPane pane = scrollPane;
+        Rectangle prefBounds = this.getPreferredBounds();
+        Dimension viewDim = pane.getViewportBorderBounds().getSize();
+
+        double realwidth = (double) prefBounds.width * this.getZoomFactor();
+        double realheight = (double) prefBounds.height * this.getZoomFactor();
+
+        double zoomX = (double) viewDim.width / realwidth;
+        double zoomY = (double) viewDim.height / realheight;
+        double zoomFactor = Math.min(zoomX, zoomY);
+        this.setZoomFactor(zoomFactor * 0.9);
+    }
+
+    //Enables Antialiasing
+    @Override
+    public void paintChildren() {
+        Object anti = getGraphics().getRenderingHint(RenderingHints.KEY_ANTIALIASING);
+        Object textAnti = getGraphics().getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING);
+
+        getGraphics().setRenderingHint(
+                RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        getGraphics().setRenderingHint(
+                RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+
+        super.paintChildren();
+
+        getGraphics().setRenderingHint(RenderingHints.KEY_ANTIALIASING, anti);
+        getGraphics().setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, textAnti);
+    }
+
+    //select provider for node selection
+    private RectangularSelectProvider createRectangularSelectProvider() {
+        return new RectangularSelectProvider() {
+
+            public void performSelection(Rectangle rectangle) {
+                HashSet<CfgNode> set = new HashSet<>();
+
+                //change to a rectangle with (x,offsetY) at the top left
+                if (rectangle.width < 0) {
+                    rectangle.x = rectangle.x + rectangle.width;
+                    rectangle.width *= -1;
+                }
+                if (rectangle.height < 0) {
+                    rectangle.y = rectangle.y + rectangle.height;
+                    rectangle.height *= -1;
+                }
+
+                for (NodeWidget n : getNodeWidgets()) {
+                    Point p = n.getLocation();
+                    if (p != null && rectangle.contains(p)) {
+                        set.add(n.getNodeModel());
+                    }
+                }
+                setNodeSelection(set);
+            }
+        };
+    }
+
+    //select decorator for node selection
+    private RectangularSelectDecorator createSelectDecorator(final CfgScene scene) {
+        return new RectangularSelectDecorator() {
+
+            public Widget createSelectionWidget() {
+                scene.cleanNodeSelection();//unselected all nodes
+                scene.revalidate();
+                return new SelectionWidget(getScene());
+            }
+        };
+    }
+
+    private MoveProvider createMoveProvider() {
+        return new MoveProvider() {
+
+            private HashMap<Widget, Point> originals = new HashMap<>();
+            private Point original = null;
+
+            public void movementStarted(Widget widget) {
+                originals.clear();
+                NodeWidget nw = (NodeWidget) widget;
+                if (selectedNodes.contains(nw.getNodeModel())) {//move current selection
+                    for (CfgNode n : selectedNodes) {
+                        Widget w = findWidget(n);
+                        originals.put(w, w.getLocation());
+                    }
+                } else {//a newly-selected node will be moved               
+                    CfgNode n = nw.getNodeModel();
+                    HashSet<CfgNode> selectedNode = new HashSet<>(1);
+                    selectedNode.add(n);
+                    setNodeSelection(selectedNode);
+                    originals.put(widget, widget.getPreferredLocation());
+                    widget.revalidate();
+                    validate();
+
+                }
+            }
+
+            public void movementFinished(Widget widget) {
+                NodeWidget nw = (NodeWidget) widget;
+                if (selectedNodes.contains(nw.getNodeModel())) {
+                    return;//to be able to move the current selection
+                }
+
+                HashSet<CfgNode> selectedNode = new HashSet<>(1);
+                selectedNode.add(nw.getNodeModel());
+                setNodeSelection(selectedNode);
+                originals.clear();
+                original = null;
+
+            }
+
+            public Point getOriginalLocation(Widget widget) {
+                if (original == null) {
+                    original = widget.getLocation();
+                }
+
+                return original;
+            }
+            //todo : find a cache algorithm which only routes edges
+            //which are intersected by bounds of the moved rectangle
+
+            public void setNewLocation(Widget widget, Point location) {
+                Point org = getOriginalLocation(widget);
+                int dx = location.x - org.x;
+                int dy = location.y - org.y;
+                for (Map.Entry<Widget, Point> entry : originals.entrySet()) {
+                    Point point = entry.getValue();
+                    entry.getKey().setPreferredLocation(new Point(point.x + dx, point.y + dy));
+                }
+                for (CfgEdge e : getEdges()) {
+                    EdgeWidget ew = (EdgeWidget) findWidget(e);
+                    if (ew.isVisible()) {
+                        ew.reroute();
+                    }
+                }
+            }
+        };
+    }
+
+    private WidgetAction createContextMenuAction(final CfgScene scene) {
+        return ActionFactory.createPopupMenuAction(new PopupMenuProvider() {
+
+            public JPopupMenu getPopupMenu(Widget widget, Point point) {
+                JPopupMenu menu = new JPopupMenu();
+                NodeWidget nw = null;
+                if (widget instanceof NodeWidget) {
+                    nw = (NodeWidget) widget;
+                    if (!selectedNodes.contains(nw.getNodeModel())) {
+                        HashSet<CfgNode> selectedNode = new HashSet<>(1);
+                        selectedNode.add(nw.getNodeModel());
+                        setNodeSelection(selectedNode);
+                    }
+                } else if (scene.getSelectedNodes().size() == 1) {
+                    nw = (NodeWidget) scene.findWidget(scene.getSelectedNodes().iterator().next());
+                }
+
+                if (nw != null) {
+                    CfgNode node = nw.getNodeModel();
+                    ArrayList<CfgNode> successors = new ArrayList<>();
+                    ArrayList<CfgNode> predecessors = new ArrayList<>();
+                    for (CfgEdge e : node.getOutputEdges()) {
+                        successors.add(e.getTargetNode());
+                    }
+                    for (CfgEdge e : node.getInputEdges()) {
+                        predecessors.add(e.getSourceNode());
+                    }
+
+                    if (predecessors.size() > 0) {
+                        Collections.sort(predecessors, new NodeNameComparator());
+                        JMenu predmenu = new JMenu("Go to predecessor");
+                        for (CfgNode n : predecessors) {
+                            GotoNodeAction action = new GotoNodeAction(n);
+                            predmenu.add(action);
+                        }
+                        menu.add(predmenu);
+                    }
+                    if (successors.size() > 0) {
+                        Collections.sort(successors, new NodeNameComparator());
+                        JMenu succmenu = new JMenu("Go to successor");
+                        for (CfgNode n : successors) {
+                            GotoNodeAction action = new GotoNodeAction(n);
+                            succmenu.add(action);
+                        }
+                        menu.add(succmenu);
+                    }
+                    if (successors.size() > 0 || predecessors.size() > 0) {
+                        menu.addSeparator();
+                    }
+                }
+
+                return menu;
+            }
+        });
+    }
+
+    @Override
+    public void zoomIn() {
+        this.setZoomFactor(this.getZoomFactor() * 1.1);
+        this.validate();
+    }
+
+    @Override
+    public void zoomOut() {
+        this.setZoomFactor(this.getZoomFactor() * 0.9);
+        this.validate();
+    }
+
+    @Override
+    public void showAll() {
+        this.zoomScene();
+        this.validate();
+    }
+
+    private class NodeNameComparator implements Comparator<CfgNode> {
+
+        public int compare(CfgNode node1, CfgNode node2) {
+            String name1 = node1.getBasicBlock().getName().substring(1);
+            String name2 = node2.getBasicBlock().getName().substring(1);
+            Integer blocknum1 = Integer.parseInt(name1);
+            Integer blocknum2 = Integer.parseInt(name2);
+            return blocknum1.compareTo(blocknum2);
+        }
+    }
+
+    private class GotoNodeAction extends AbstractAction {
+
+        CfgNode node;
+
+        GotoNodeAction(CfgNode node) {
+            super(node.getBasicBlock().getName());
+            this.node = node;
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            Set<CfgNode> nodes = new HashSet<>(1);
+            nodes.add(node);
+            setNodeSelection(nodes);
+            centerSelection();
+        }
+    }
+
+    private SceneListener createSceneListener(final CfgScene scene) {
+        return new SceneListener() {
+
+            public void sceneRepaint() {
+            }
+
+            public void sceneValidating() {
+            }
+
+            public void sceneValidated() {
+                if (scene.isLoopClusterVisible()) { //update only if visible
+                    for (LoopClusterWidget cw : getLoopidx2clusterwidget().values()) {
+                        cw.updateClusterBounds();
+                    }
+                }
+                for (EdgeSwitchWidget esw : inputSwitches.values()) {
+                    esw.updatePosition();
+                }
+
+                for (EdgeSwitchWidget esw : outputSwitches.values()) {
+                    esw.updatePosition();
+                }
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeSwitchWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,290 @@
+package at.ssw.visualizer.cfg.graph;
+
+import at.ssw.visualizer.cfg.model.CfgEdge;
+import at.ssw.visualizer.cfg.model.CfgNode;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.util.ArrayList;
+import java.util.Collection;
+import org.netbeans.api.visual.action.ActionFactory;
+import org.netbeans.api.visual.action.SelectProvider;
+import org.netbeans.api.visual.action.TwoStateHoverProvider;
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.model.ObjectState;
+import org.netbeans.api.visual.widget.Widget;
+
+
+public class EdgeSwitchWidget extends Widget {
+    private final static Color color_enabled = Color.gray;
+    private final static Color color_hover = Color.lightGray; 
+    private float width=1;
+    private float height=1;
+    private CfgScene scene;
+    private NodeWidget nodeWidget;    
+    private boolean output;
+    private WidgetAction hoverAction;
+    private static final String TT_HIDE_EDGES = "Hide Edges";
+    private static final String TT_SHOW_EDGES = "Show Edges";   
+    private static SelectProvider selectProvider = createSelectProvider();
+     
+    
+    public EdgeSwitchWidget(final CfgScene scene, NodeWidget nodeWidget, boolean output) {        
+        super(scene);
+        this.scene = scene;   
+        this.output = output;
+        this.nodeWidget = nodeWidget;  
+  
+        this.getActions().addAction(ActionFactory.createSelectAction(selectProvider));
+        TwoStateHoverProvider ts = new TsHover(this);   
+        WidgetAction wa = ActionFactory.createHoverAction(ts);
+        this.hoverAction = wa;
+        this.getActions().addAction(wa);
+        scene.getActions().addAction(wa);
+        this.setToolTipText(TT_HIDE_EDGES);      
+        this.setForeground(color_enabled);
+        this.setState(ObjectState.createNormal());
+    }
+    
+    
+    @Override
+    protected Rectangle calculateClientArea() {
+       if (this.nodeWidget.getBounds() == null) return new Rectangle(0, 0, 1, 1);
+       int hw = (int) (this.width / 2);
+       int hh = (int) (this.height /2);
+       
+       return new Rectangle(-hw, -hh, 2*hw, 2*hh); 
+   }    
+     
+   
+    public void updatePosition() { 
+        if (this.nodeWidget.getBounds() != null) {   
+            this.width = nodeWidget.getBounds().width*9;
+            this.width /=10;
+            this.height = nodeWidget.getBounds().height/4;      
+            int offset=(int)(2 * (height / 3));
+                        
+            Rectangle bounds = nodeWidget.getBounds();
+            Point location = nodeWidget.getLocation();
+          
+            Point newLoc = new Point();           
+            newLoc.x = location.x;
+             
+            if(output) {               
+                newLoc.y = +location.y + bounds.height/2+offset;      
+            }else {            
+                newLoc.y = location.y - bounds.height/2-offset;
+            }          
+            this.setPreferredLocation(newLoc);           
+        }           
+    }
+ 
+    private Collection<CfgEdge> getEdges(){
+        Collection<CfgEdge> edges;
+        CfgNode node = nodeWidget.getNodeModel();
+        if (output) {
+            edges = scene.findNodeEdges(node, true, false);
+        } else {
+            edges = scene.findNodeEdges(node, false, true);
+        }
+        return edges;
+    }
+ 
+    //change visibility for all Edges
+    public void changeEdgeVisibility(boolean visible){
+        Collection<CfgEdge> edges = this.getEdges();  
+            
+        for(CfgEdge e: edges) {
+            EdgeWidget ew = (EdgeWidget) scene.findWidget(e);
+            if(visible != ew.isEdgeVisible()){              
+                ew.setEdgeVisible(visible);     
+                if(output){
+                    scene.getInputSwitch(e.getTargetNode()).updateStatus();
+                } else {
+                    scene.getOutputSwitch(e.getSourceNode()).updateStatus();
+                }              
+            }
+        }
+        if(visible)    
+            this.setToolTipText(TT_HIDE_EDGES); 
+        else 
+            this.setToolTipText(TT_SHOW_EDGES);
+   
+        this.setForeground(color_enabled);
+        this.bringToBack();
+        ObjectState os = this.getState();   
+        this.setState(os.deriveSelected(!visible));
+    }
+    
+    /**
+     *  Update the status of the switch to the current state of the edges
+     *  usually needed when the opposit switch changes the state
+     */
+    private void updateStatus(){
+        Collection<CfgEdge> edges = this.getEdges(); 
+        boolean hiddenFound=false;
+        for(CfgEdge e: edges) {
+            EdgeWidget ew = (EdgeWidget) scene.findWidget(e);
+            if(!ew.isVisible()) {
+                hiddenFound=true;
+                break;
+            }
+        }        
+        ObjectState os = this.getState();
+        if(os.isSelected() && !hiddenFound) {
+            this.setState(os.deriveSelected(false));
+            setToolTipText(TT_HIDE_EDGES);
+        } else if (!os.isSelected() && hiddenFound) {
+            this.setState(os.deriveSelected(true));
+            setToolTipText(TT_SHOW_EDGES); 
+        }
+        this.revalidate();
+    }
+    
+
+    public void startPreview() {        
+        ObjectState os = this.getState();
+        
+        for(CfgEdge e : getEdges()) {
+            EdgeWidget ew = (EdgeWidget) scene.findWidget(e);
+            if(!os.isSelected() || !ew.isVisible()){             
+                ObjectState edgeState = ew.getState();              
+                ew.setState(edgeState.deriveHighlighted(true));
+            }
+        }               
+    }
+    
+    public void endPreview(){       
+       for(CfgEdge e : getEdges()) {
+            EdgeWidget ew = (EdgeWidget) scene.findWidget(e);
+            ObjectState os = ew.getState();          
+            ew.setState(os.deriveHighlighted(false));
+        }      
+    }
+  
+    /**
+     * shows or hides the edges of the switch
+     */
+    public void switchEdges() { 
+        endPreview();
+        ObjectState os = this.getState();
+        Collection<CfgEdge> edges = this.getEdges(); 
+        ArrayList<CfgEdge> updates = new ArrayList<>();
+        boolean visible=os.isSelected();
+        this.setState(os.deriveSelected(!visible));     
+        for(CfgEdge e: edges) {
+            EdgeWidget ew = (EdgeWidget) scene.findWidget(e);
+                if(ew.isEdgeVisible() != visible){
+                    updates.add(e);
+                    ew.setEdgeVisible(visible);
+                    if(output){
+                        scene.getInputSwitch(e.getTargetNode()).updateStatus();
+                    } else {
+                        scene.getOutputSwitch(e.getSourceNode()).updateStatus();
+                    }      
+                }
+        }
+        if(visible)
+             this.setToolTipText(TT_HIDE_EDGES);    
+        else
+             this.setToolTipText(TT_SHOW_EDGES);    
+               
+        revalidate();   
+    }
+  
+  
+
+ 
+    private class TsHover implements TwoStateHoverProvider {       
+        EdgeSwitchWidget tw;    
+       
+        TsHover(EdgeSwitchWidget tw) {
+            this.tw = tw;
+        }
+       
+        public void unsetHovering(Widget w) {
+            w.setForeground(color_enabled);  
+            ObjectState state = w.getState();          
+            w.setState(state.deriveWidgetHovered(false));           
+            w.bringToBack();
+            endPreview();
+        }
+
+        public void setHovering(Widget w) {        
+            ObjectState state = w.getState();          
+            w.setState(state.deriveWidgetHovered(true));          
+            w.setForeground(color_hover);
+            w.bringToFront();
+            nodeWidget.bringToFront();                
+            startPreview();
+        }
+    }
+    
+    @Override
+    public void paintWidget() {   
+        ObjectState os = this.getState();       
+        if(!os.isHovered() && !os.isSelected()) return; //all previewEdges visible and not hovering, 
+                                                        //no need to paint the switch         
+        float hw = width/2;    
+        Polygon pol = new Polygon();
+        pol.addPoint(0,(int) -height/2); 
+        pol.addPoint((int)hw,(int) height/2);
+        pol.addPoint((int)-hw,(int) height/2);  
+        Graphics2D gr = getGraphics();
+        gr.setColor(this.getForeground());
+        BasicStroke bs = new BasicStroke(2.0f, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
+        gr.setStroke(bs);
+        AffineTransform previousTransform;
+        previousTransform = gr.getTransform ();
+        if(output) {
+            if(os.isSelected() ){//hidden
+                 gr.scale(1.0, -1.0);
+            }
+        } else { //input switch
+            if(os.isHovered() && !os.isSelected()){
+                 gr.scale(1.0, -1.0);
+            }     
+        }            
+        gr.fillPolygon(pol);
+        gr.setTransform(previousTransform);
+        
+    }
+    
+   
+    
+    //the constructor adds the hover WidgetAction to the scene
+    //the action is removed from the scene when the object gets destroyed
+    @Override
+    protected void finalize() throws Throwable { 
+        this.getScene().getActions().removeAction(hoverAction);
+        this.getActions().removeAction(hoverAction);
+    }
+    
+    @Override
+    public String toString(){
+        return "EDGESWITCH("+this.nodeWidget.getNodeModel().toString()+")";
+    }
+    
+    private static SelectProvider createSelectProvider() {
+        return new SelectProvider(){
+            public boolean isAimingAllowed(Widget arg0, Point arg1, boolean arg2) {
+                return false;
+            }
+            
+            public boolean isSelectionAllowed(Widget arg0, Point arg1, boolean arg2) {
+                return true;
+            }
+            
+            public void select(Widget w, Point arg1, boolean arg2) {              
+                if(w instanceof EdgeSwitchWidget){
+                    EdgeSwitchWidget tw = (EdgeSwitchWidget) w;                    
+                    tw.switchEdges();
+                }                                    
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,97 @@
+package at.ssw.visualizer.cfg.graph;
+
+import at.ssw.visualizer.cfg.model.CfgEdge;
+import at.ssw.visualizer.cfg.preferences.CfgPreferences;
+import at.ssw.visualizer.cfg.visual.BezierWidget;
+import at.ssw.visualizer.cfg.visual.SplineConnectionWidget;
+import org.netbeans.api.visual.anchor.AnchorShapeFactory;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Stroke;
+import org.netbeans.api.visual.anchor.AnchorShape;
+import org.netbeans.api.visual.model.ObjectState;
+
+//public class EdgeWidget extends BezierWidget {
+public class EdgeWidget extends SplineConnectionWidget {
+    
+    private boolean visible=true;//to store the visible state when entering the preview 
+    protected static final Stroke selectedStroke = new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
+    protected static final Stroke defaultStroke = new BasicStroke(1.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
+    protected static final Stroke previewStroke = new BasicStroke(
+            0.5f,                      // Width
+            BasicStroke.CAP_SQUARE,    // End cap
+            BasicStroke.JOIN_MITER,    // Join style
+            10.0f,                     // Miter limit
+            new float[] {5.0f, 5.0f},  // Dash pattern
+            0.0f);              
+    
+    
+    
+    public EdgeWidget(CfgScene scene, CfgEdge edge) {
+        super(scene);       
+        Color lineColor;
+        CfgPreferences prefs = CfgPreferences.getInstance();
+        
+        if(edge.isBackEdge()) 
+            lineColor = prefs.getBackedgeColor();       
+        else if (edge.isXhandler())
+            lineColor = prefs.getExceptionEdgeColor();
+        else    
+            lineColor = prefs.getEdgeColor();
+        
+        setLineColor(lineColor);
+        AnchorShape as;
+        if(edge.isReflexive())//small Arrow
+            as = AnchorShapeFactory.createTriangleAnchorShape(6, true, false, 5);
+        else
+            as =AnchorShapeFactory.createTriangleAnchorShape(10, true, false, 9);
+    
+        setTargetAnchorShape(as);  
+        setToolTipText(edge.toString());              
+    }
+ 
+    public CfgEdge getEdgeModel() {
+        CfgScene scene = (CfgScene) this.getScene();
+        return (CfgEdge) scene.findObject(this);
+    }
+    
+    public void setEdgeVisible(boolean visible) {
+        this.visible=visible;
+        this.setVisible(visible);
+        this.reroute();
+        this.revalidate();
+    }
+    
+    
+    public boolean isEdgeVisible(){
+        return visible;
+    }
+    
+        
+    @Override
+    public void notifyStateChanged(ObjectState oldState, ObjectState newState) {
+       setForeground (getLineColor());
+      
+       if(newState.isHighlighted() && !oldState.isHighlighted()){
+            this.setStroke(previewStroke);
+            this.setVisible(true);
+       } else {
+           if(newState.isSelected()){
+                this.setStroke(selectedStroke);
+           } else {
+                this.setStroke(defaultStroke);
+           }
+           if(this.isEdgeVisible()){
+                this.setVisible(true);
+           } else {
+                this.setVisible(false);
+           }
+       }       
+    }
+    
+    
+    @Override
+    public String toString(){
+        return "EdgeWidget[" + getEdgeModel().toString() + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/LoopClusterWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,107 @@
+package at.ssw.visualizer.cfg.graph;
+
+import at.ssw.visualizer.cfg.model.LoopInfo;
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import org.netbeans.api.visual.action.ActionFactory;
+import org.netbeans.api.visual.action.EditProvider;
+import org.netbeans.api.visual.border.BorderFactory;
+import org.netbeans.api.visual.widget.Widget;
+
+public class LoopClusterWidget extends Widget implements Comparable<LoopClusterWidget> {
+    private static final int INSET = 10;//min space between node members and cluster border
+    private static final int DASHSIZE = 10;  
+    private Color color = Color.BLUE;
+    private int loopIndex;
+    private int loopDepth; 
+    private CfgScene cfgscene;
+    private ArrayList<NodeWidget> members = new ArrayList<>();
+  
+    public LoopClusterWidget(CfgScene scene,  int loopdepth, final int loopindex) {
+        super(scene);
+        this.cfgscene = scene;
+        this.loopIndex = loopindex;
+        this.loopDepth = loopdepth;          
+        this.setBorder(BorderFactory.createDashedBorder(color, DASHSIZE, DASHSIZE/2, true));          
+        this.getActions().addAction(ActionFactory.createEditAction( new EditProvider() { //double click action
+            public void edit(Widget w) {
+                if(w instanceof LoopClusterWidget){                 
+                    for(LoopInfo info : cfgscene.getCfgEnv().getLoopMap().values()){
+                        if(info.getLoopIndex() == loopindex){              
+                            cfgscene.setNodeSelection(info.getMembers());                         
+                            break;
+                        }
+                    }   
+                }
+            }
+        }));
+               
+    }
+
+    public List<NodeWidget> getMembers() {
+        return members;
+    }
+
+    public int getLoopIndex() {
+        return loopIndex;
+    }
+    
+    public void addMember(NodeWidget nw) {
+        assert(!this.members.contains(nw));        
+        members.add(nw);       
+    }
+
+    public boolean removeMember(NodeWidget nw) {
+        if(this.members.contains(nw)){
+            members.remove(nw);       
+            return true;
+        }
+        return false;
+    }
+  
+    public void setrandomColor(){
+        if(this.loopDepth == 0 ) return; 
+        Random rand = new Random();
+        Color randColor = Color.getHSBColor(rand.nextFloat()%360,0.1f,1.0f);      
+        this.setBackground(randColor);
+    }
+    
+    //updates the bounds of the widget,
+    //and revalidates the widget if a membernode changed the scene position
+    public void updateClusterBounds(){      
+        Rectangle boundRect=null;
+        
+        for(NodeWidget nw : this.members){
+            if(boundRect==null){
+                boundRect = nw.convertLocalToScene(nw.getBounds());  
+            } else {
+                boundRect = boundRect.union(nw.convertLocalToScene(nw.getBounds()));
+            }  
+        }
+        if(boundRect==null) return;
+        for(Widget w : this.getChildren()) {
+            if(w instanceof LoopClusterWidget) {            
+                LoopClusterWidget lc = (LoopClusterWidget)w;
+                lc.updateClusterBounds();
+                boundRect = boundRect.union(w.convertLocalToScene(w.getBounds()));
+            }
+        }
+       
+        boundRect.grow(INSET, INSET);
+        this.setPreferredBounds(boundRect);               
+    }
+    
+    
+    public int compareTo(LoopClusterWidget o) {
+        return new Integer(this.loopDepth).compareTo(o.loopDepth);
+    }
+    
+    
+    @Override
+    public String toString(){
+        return "LoopCluster: [DEPTH "+this.loopDepth+ "] [INDEX "+this.loopIndex+"]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/NodeWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,153 @@
+package at.ssw.visualizer.cfg.graph;
+
+import at.ssw.visualizer.cfg.model.CfgNode;
+import at.ssw.visualizer.cfg.preferences.CfgPreferences;
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.font.FontRenderContext;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import org.netbeans.api.visual.border.BorderFactory;
+import org.netbeans.api.visual.model.ObjectState;
+import org.netbeans.api.visual.widget.Widget;
+
+
+public class NodeWidget extends Widget  {    
+    
+    
+    //basic block node dimension
+    private final int halfheight=12;
+    private final int halfwidth=17;
+      
+    private final int height=halfheight*2+1;  
+    private final int width=halfwidth*2+1;     
+    private final int arcHeight=(halfheight/4)*3;
+    private final int arcWidth = arcHeight; 
+    private final int FONT_MAXSIZE=18;
+    
+    private int borderWidth;
+    private boolean nodeColorCustomized;
+    private String text;
+    private Rectangle2D fontRect;
+    private Color nodeColor;
+    
+    protected static final Color HOVER_BACKGROUND = new Color(0xEEEEEE);
+    protected static final Color HOVER_FOREGROUND = new Color(0xCDCDCD);
+
+    public NodeWidget(CfgScene scene, CfgNode nodeModel ){        
+        super(scene);   
+        this.setToolTipText("<html>" + nodeModel.getDescription().replaceAll("\n", "<br>") + "</html>");
+        this.text = nodeModel.getBasicBlock().getName();   
+        this.borderWidth = nodeModel.getLoopDepth()+1;           
+        this.setBorder(BorderFactory.createRoundedBorder(arcWidth+borderWidth, arcHeight+borderWidth, borderWidth, borderWidth, Color.BLACK, Color.BLACK));
+        CfgPreferences prefs = CfgPreferences.getInstance();
+        Color color = prefs.getFlagsSetting().getColor(nodeModel.getBasicBlock().getFlags());
+        this.nodeColorCustomized = (color!=null);
+        this.nodeColor = (nodeColorCustomized) ? color : prefs.getNodeColor();
+        this.adjustFont(null);   
+    }
+
+    public void setBorderColor(Color color){ 
+        this.setBorder(BorderFactory.createRoundedBorder(arcWidth+borderWidth, arcHeight+borderWidth, borderWidth, borderWidth, color, color));
+    }
+    
+    public boolean isNodeColorCustomized() {    
+        return nodeColorCustomized;        
+    }
+    
+    //sets a customColor node color
+    public void setNodeColor(Color color, boolean customColor) {
+        this.nodeColorCustomized=customColor;
+        this.nodeColor=color;
+        this.revalidate();
+    }
+    
+    public Color getNodeColor() {
+        return this.nodeColor;
+    }
+    
+    public CfgNode getNodeModel() {
+        CfgScene scene = (CfgScene) this.getScene();
+        return (CfgNode) scene.findObject(this);    
+    }
+      
+   
+    @Override
+    public void notifyStateChanged(ObjectState oldState, ObjectState newState) {
+        if(!oldState.equals(newState))
+            this.revalidate();
+        if(!oldState.isSelected() && newState.isSelected())
+            this.bringToFront();
+    }
+       
+    @Override
+    protected Rectangle calculateClientArea() {       
+        return new Rectangle(-(halfwidth+1), -(1+halfheight), width+1, height+1);//add border
+    }
+
+    public void adjustFont(Font font){
+        if(font==null)
+            font = CfgPreferences.getInstance().getTextFont();
+        if(font.getSize()>FONT_MAXSIZE){
+            font = new Font(font.getFamily(), font.getStyle(), FONT_MAXSIZE);
+        }
+        int size=font.getSize();
+        int fontStyle = font.getStyle();
+        String fontName = font.getFamily();
+        FontRenderContext frc = new FontRenderContext(new AffineTransform(), false, false);
+        Rectangle2D bounds = font.getStringBounds(text, frc);
+        while(size > 1 && bounds.getWidth() > width) {
+            font = new Font(fontName, fontStyle, --size);
+            bounds = font.getStringBounds(text, frc);
+        }       
+        this.fontRect=bounds;
+        this.setFont(font);
+    }
+
+    @Override
+    protected void paintWidget() {     
+        Graphics2D gr = getGraphics(); 
+        gr.setColor(nodeColor); 
+        Insets borderInsets  = this.getBorder().getInsets();    
+        RoundRectangle2D.Float innerRect = new RoundRectangle2D.Float(-(halfwidth+1), -(halfheight+1), width+1, height+1,arcWidth-1, arcHeight-1);    
+        gr.fill(innerRect);
+        gr.setColor(getForeground()); 
+        gr.setFont(getFont());
+        float textX  = (float)( - fontRect.getCenterX());
+        float textY  = (float)( - fontRect.getCenterY());                   
+        gr.drawString(text, textX, textY); 
+            
+        RoundRectangle2D.Float outerRect = new RoundRectangle2D.Float(-(halfwidth+borderInsets.left + 1), -(halfheight+borderInsets.top + 1), 
+            width+borderInsets.left + borderInsets.right + 1, height + borderInsets.top + borderInsets.bottom + 1, 
+            arcWidth + borderWidth, arcHeight + borderWidth); 
+
+        ObjectState os =this.getState();
+        if(os.isSelected()){
+            Composite composite = gr.getComposite();
+            gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));                     
+            gr.setColor(CfgPreferences.getInstance().getSelectionColorForeground());
+            gr.fill(outerRect);
+            gr.setColor(CfgPreferences.getInstance().getSelectionColorBackground());            
+            gr.setComposite(composite);       
+        }  
+        if(os.isHovered()){
+            Composite composite = gr.getComposite();
+            gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
+            gr.setColor(HOVER_FOREGROUND);
+            gr.fill(outerRect); 
+            gr.setColor(HOVER_BACKGROUND);
+            gr.setComposite(composite);        
+        }       
+    }  
+    
+    @Override
+    public String toString() {
+        return "NodeWidget[" + getNodeModel().getBasicBlock().getName() + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SelectionWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,39 @@
+package at.ssw.visualizer.cfg.graph;
+
+import at.ssw.visualizer.cfg.preferences.CfgPreferences;
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import org.netbeans.api.visual.widget.Scene;
+import org.netbeans.api.visual.widget.Widget;
+
+
+public class SelectionWidget extends Widget {
+    public SelectionWidget(Scene scene) {
+        super(scene);
+    }
+    
+    public static void renderSelectedRect(Graphics2D gr, Rectangle rect) {
+        if (rect == null) {
+            return;
+        }
+        gr.setColor(CfgPreferences.getInstance().getSelectionColorBackground());
+        gr.fillRect(rect.x, rect.y, rect.width, rect.height);
+        gr.setColor(CfgPreferences.getInstance().getSelectionColorForeground());
+    }
+
+    public void renderSelectionRectangle(Graphics2D gr, Rectangle selectionRectangle) {
+        Composite composite = gr.getComposite();
+        gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
+       
+        renderSelectedRect(gr, selectionRectangle);
+        gr.setComposite(composite);
+    }
+    
+    @Override
+    public void paintWidget(){       
+        this.renderSelectionRectangle(this.getGraphics(), this.getBounds());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SymmetricAnchor.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,157 @@
+package at.ssw.visualizer.cfg.graph;
+
+import org.netbeans.api.visual.widget.Widget;
+import org.netbeans.api.visual.anchor.Anchor;
+import java.awt.*;
+
+
+/**
+ * This Anchor can be used with symmetric edges to create parallel Edges.
+ * Two Directed Edges are symmetric if they are connecting the same Nodes in different directions.
+ * e.g.  Nodes (1, 2) Edges(a , b)  with (1)-a->(2)  ,  (2)-b->(1)  
+ * Start-/End positions are calculated with a fixed offset to prevent edges from overlapping. 
+ * If the edges are drawn as straight lines they will appear as parallel edges.
+ */
+
+public final class SymmetricAnchor extends Anchor {
+    
+   private final static int OFFSET = 10;
+   private boolean includeBorders;  
+   private int offx;
+   private int offy;
+   
+   public SymmetricAnchor (Widget widget, boolean includeBorders, boolean source) {
+        super (widget);
+        this.includeBorders = includeBorders;        
+        if (source) {
+            offx = OFFSET;
+            offy = OFFSET;        
+        }
+        else {
+            offx = -OFFSET;
+            offy = -OFFSET;
+        }
+    }
+
+    public Result compute (Entry entry) {        
+        Point relatedLocation = //center of the widget 
+                getRelatedSceneLocation ();
+        Point oppositeLocation = //center of the widget
+                getOppositeSceneLocation (entry);
+
+        Widget widget = getRelatedWidget ();
+        Rectangle bounds = widget.getBounds ();
+        if (! includeBorders) {
+            Insets insets = widget.getBorder ().getInsets ();
+            bounds.x += insets.left;
+            bounds.y += insets.top;
+            bounds.width -= insets.left + insets.right;
+            bounds.height -= insets.top + insets.bottom;
+        }
+      
+        bounds = widget.convertLocalToScene (bounds);
+       
+        if (bounds.isEmpty ()  || relatedLocation.equals (oppositeLocation))
+            return new Anchor.Result (relatedLocation, Anchor.DIRECTION_ANY);
+
+        float dx  //distance  x-axis
+                = oppositeLocation.x - relatedLocation.x;
+        float dy  //distance y-axis  
+                = oppositeLocation.y - relatedLocation.y;
+       
+        
+        float ddx 
+                = Math.abs (dx) / (float) bounds.width;
+        float ddy = 
+                Math.abs (dy) / (float) bounds.height;
+
+        Anchor.Direction direction;
+      
+
+        if (ddx >= ddy) {
+            if(dx >= 0.0f){        
+                direction = Direction.RIGHT;
+                relatedLocation.y -= offy;
+            } else {
+                direction = Direction.LEFT;
+                relatedLocation.y += offy;
+            }         
+        } else {
+            if(dy >= 0.0f){
+                direction = Direction.BOTTOM;
+                relatedLocation.x += offx;
+            } else {
+                direction = Direction.TOP;
+                relatedLocation.x -= offx;            
+            }           
+        }
+        
+
+        float scale = 0.5f / Math.max (ddx, ddy);
+
+        float ex = scale * dx;
+        float ey = scale * dy;
+        
+        Point point = new Point (Math.round (relatedLocation.x + ex), Math.round (relatedLocation.y + ey));
+            
+         if(direction == Direction.RIGHT) {
+             int top = bounds.y;//-bounds.height;// left y of the widget
+             int bottom = bounds.y + bounds.height;// right y of the widget
+             if(point.y < top) {//above the widget
+                 int cor = top-point.y;
+                 point.x -= cor;
+                 point.y += cor;              
+             } else if ( point.y > bottom) {
+                 int cor = point.y-bottom;
+                 point.x -= cor;
+                 point.y -= cor;
+             }
+             
+         } else if (direction == Direction.LEFT) {
+             int top = bounds.y;//-bounds.height;// left y of the widget
+             int bottom = bounds.y + bounds.height;// right y of the widget
+                         
+           
+                        
+             if(point.y < top) {//above the widget
+                 int cor = top-point.y;
+                 point.x += cor;
+                 point.y += cor;
+             } else if ( point.y > bottom) {              
+                int cor = bottom-point.y;
+                point.x -= cor;
+                point.y += cor;
+             }
+            
+                      
+         } else if (direction == Direction.BOTTOM) {
+             int left = bounds.x;//-bounds.height;// left y of the widget
+             int right = bounds.x + bounds.width;// right y of the widget
+             if(point.x < left) {//above the widget
+                int cor = left-point.x;                
+                point.x += cor;
+                point.y -= cor;
+             } else if ( point.x > right) {
+                int cor = point.x- right;
+                point.x -= cor;
+                point.y -= cor;
+             }
+         
+         } else if (direction == Direction.TOP) {
+            int left = bounds.x;//-bounds.height;// left y of the widget
+            int right = bounds.x + bounds.width;// right y of the widget
+            if(point.x < left) {//above the widget
+                int cor = left-point.x;
+                point.x += cor;
+                point.y += cor;
+             } else if ( point.x > right) {
+                 int cor = point.x - right;
+                 point.x -= cor;
+                 point.y += cor;
+             }
+         
+         }          
+        
+        return new Anchor.Result (point, direction);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalCompoundLayout.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,102 @@
+package at.ssw.visualizer.cfg.graph.layout;
+
+import at.ssw.visualizer.cfg.graph.CfgScene;
+import at.ssw.visualizer.cfg.model.CfgEdge;
+import at.ssw.visualizer.cfg.model.CfgNode;
+import at.ssw.visualizer.cfg.model.LoopInfo;
+import java.awt.Point;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.draw2d.geometry.Insets;
+import org.netbeans.api.visual.graph.layout.GraphLayout;
+import org.netbeans.api.visual.graph.layout.UniversalGraph;
+import org.eclipse.draw2d.graph.CompoundDirectedGraph;
+import org.eclipse.draw2d.graph.CompoundDirectedGraphLayout;
+import org.eclipse.draw2d.graph.Edge;
+import org.eclipse.draw2d.graph.EdgeList;
+import org.eclipse.draw2d.graph.Node;
+import org.eclipse.draw2d.graph.NodeList;
+import org.eclipse.draw2d.graph.Subgraph;
+import org.netbeans.api.visual.widget.Widget;
+
+public class HierarchicalCompoundLayout extends GraphLayout<CfgNode, CfgEdge> {
+           
+    private static final int TOP_BORDER = 20;
+    private static final int LEFT_BORDER = 20;
+    private int PADDING = 20;
+    private static final int INSET = 20;
+    private CfgScene scene;      
+       
+    public HierarchicalCompoundLayout(CfgScene scene){
+        this.scene = scene;         
+    }
+    
+    @Override
+    protected void performGraphLayout(UniversalGraph<CfgNode, CfgEdge> ug) {          
+        CompoundDirectedGraph dg = new CompoundDirectedGraph();
+        CompoundDirectedGraphLayout layout = new CompoundDirectedGraphLayout();
+        NodeList nodeList = dg.nodes;
+        EdgeList edgeList = dg.edges;
+                
+        Map<Integer, Subgraph> idx2graph = new HashMap<>();
+        Subgraph base = new Subgraph(0);
+        idx2graph.put(0, base);
+        base.insets=getInsets();
+        for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){           
+            Subgraph subg = new Subgraph(info.getLoopIndex());   
+            subg.insets=getInsets();
+            idx2graph.put(info.getLoopIndex(), subg);
+        }
+            
+        for(CfgNode n : scene.getCfgEnv().getNodes() ) {
+            Widget nodeWidget = scene.findWidget(n);
+            Node node = new Node(n);
+            node.width=nodeWidget.getBounds().width;
+            node.height = nodeWidget.getBounds().height;
+            node.setPadding(new Insets(PADDING, PADDING, PADDING, PADDING));          
+            Subgraph subg = idx2graph.get(n.getLoopIndex());
+            assert(subg != null);
+            node.setParent(subg);
+            subg.addMember(node);
+            nodeList.add(node);
+          
+        }             
+        nodeList.addAll(idx2graph.values());         
+        for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){
+            Subgraph subg = idx2graph.get(info.getLoopIndex());
+            if(info.getParent() != null){
+                Subgraph parentsubg = idx2graph.get(info.getParent().getLoopIndex());
+                Edge edge = new Edge(parentsubg, subg);
+                parentsubg.addMember(subg);
+                subg.setParent(parentsubg);              
+                edgeList.add(edge);     
+            }               
+        }   
+        for(CfgEdge e : scene.getCfgEnv().getEdges() ) {                      
+            if(e.isBackEdge()) continue;
+            Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), nodeList.getNode(e.getTargetNode().getNodeIndex()));
+            edgeList.add(edge);
+        } 
+        layout.visit(dg);
+                
+        for(Object obj : dg.nodes){           
+            Node n = (Node) obj;
+            if(n.data instanceof CfgNode){
+                CfgNode cfgNode = (CfgNode) n.data;              
+                Point pos = new Point(n.x + LEFT_BORDER, n.y + TOP_BORDER);
+                Point scenepos = scene.convertLocalToScene(pos);
+                this.setResolvedNodeLocation(ug, cfgNode, scenepos); 
+            }
+        }      
+    }
+    
+    @Override
+    protected void performNodesLayout(UniversalGraph<CfgNode, CfgEdge> ug, Collection<CfgNode> collection) {        
+    }
+    
+    private Insets getInsets(){             
+        return new Insets(INSET, INSET, INSET, INSET);        
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalNodeLayout.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,69 @@
+package at.ssw.visualizer.cfg.graph.layout;
+
+import at.ssw.visualizer.cfg.graph.CfgScene;
+import at.ssw.visualizer.cfg.model.CfgEdge;
+import at.ssw.visualizer.cfg.model.CfgNode;
+import java.awt.Point;
+import java.util.Collection;
+import org.netbeans.api.visual.graph.layout.GraphLayout;
+import org.netbeans.api.visual.graph.layout.UniversalGraph;
+import org.eclipse.draw2d.graph.DirectedGraph;
+import org.eclipse.draw2d.graph.DirectedGraphLayout;
+import org.eclipse.draw2d.graph.Edge;
+import org.eclipse.draw2d.graph.EdgeList;
+import org.eclipse.draw2d.graph.Node;
+import org.eclipse.draw2d.graph.NodeList;
+import org.netbeans.api.visual.widget.Widget;
+
+
+public class HierarchicalNodeLayout extends GraphLayout<CfgNode, CfgEdge> {
+           
+    private static final int TOP_BORDER = 20;
+    private static final int LEFT_BORDER = 40;    
+    
+    private CfgScene scene;  
+    
+    public HierarchicalNodeLayout(CfgScene scene){
+        this.scene = scene;      
+    }
+    
+    @Override
+    protected void performGraphLayout(UniversalGraph<CfgNode, CfgEdge> ug) {  
+        DirectedGraph dg = new DirectedGraph();
+        DirectedGraphLayout layout = new DirectedGraphLayout();
+       
+        NodeList nodeList = dg.nodes;
+        EdgeList edgeList = dg.edges;
+        
+        for(CfgNode n : scene.getCfgEnv().getNodes() ) {
+            Widget nodeWidget = scene.findWidget(n);
+            Node node = new Node(n);           
+            node.width=nodeWidget.getBounds().width;
+            node.height = nodeWidget.getBounds().height;         
+            nodeList.add(node);
+        }
+        
+        for(CfgEdge e : scene.getCfgEnv().getEdges() ) {
+            if(e.isBackEdge()) continue;
+            Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), 
+                    nodeList.getNode(e.getTargetNode().getNodeIndex()));            
+            edgeList.add(edge);
+        }        
+      
+        layout.visit(dg);
+        
+        for(Object obj : dg.nodes){
+            Node n = (Node) obj;
+            CfgNode cfgNode  = (CfgNode) n.data;
+            Point pos = new Point(n.x + LEFT_BORDER , n.y + TOP_BORDER);
+            Point scenepos = scene.convertLocalToScene(pos);
+            setResolvedNodeLocation(ug, cfgNode, scenepos);              
+        }
+        
+    }
+
+    @Override
+    protected void performNodesLayout(UniversalGraph<CfgNode, CfgEdge> ug, Collection<CfgNode> collection) {        
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/Icons.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,18 @@
+package at.ssw.visualizer.cfg.icons;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public class Icons {
+    private static final String PATH = "at/ssw/visualizer/cfg/icons/";
+    
+    public static final String CFG = PATH + "cfg.gif";
+    
+    public static final String ICON_ZOOMIN = PATH + "zoomin.gif";
+    public static final String ICON_ZOOMOUT = PATH + "zoomout.gif";
+    public static final String ICON_DEFAULT = PATH + "arrangebfs.gif";
+
+    private Icons() {
+    }
+}
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangebfs.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangehier.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangeloop.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/autosize_selection.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/bezierrouter.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cfg.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cfg32.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cluster.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/color.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/combine.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/combine_disabled.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/disk.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/fanrouter.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/hideedges.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/hideedges_disabled.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/manhattanrouter.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/showedges.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/showedges_disabled.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/split.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/split_disabled.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/layer.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,42 @@
+<?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="OptionsDialog">
+        <file name="CFGOptions.instance">
+            <attr name="instanceClass" stringvalue="at.ssw.visualizer.cfg.preferences.CFGOptionsCategory"/>
+            <attr name="position" intvalue="1"/>
+        </file>              
+    </folder>   
+    <folder name="CompilationViewer">
+        <folder name="CFG">
+            <folder name="Actions">
+                <file name="com-oracle-graal-visualizer-cfg-RouterAction.instance">
+                    <attr name="displayName" stringvalue="Use bezier routing"/>
+                    <attr methodvalue="org.openide.awt.Actions.checkbox" name="instanceCreate"/>
+                    <attr name="iconBase" stringvalue="at/ssw/visualizer/cfg/icons/bezierrouter.gif"/>
+                    <attr name="preferencesNode" methodvalue="at.ssw.visualizer.cfg.graph.CfgScene.getPreferences"/>
+                    <attr name="preferencesKey" stringvalue="router"/>
+                </file>
+                <file name="com-oracle-graal-visualizer-cfg-LoopClusterAction.instance">
+                    <attr name="displayName" stringvalue="Show loop clusters"/>
+                    <attr methodvalue="org.openide.awt.Actions.checkbox" name="instanceCreate"/>
+                    <attr name="iconBase" stringvalue="at/ssw/visualizer/cfg/icons/cluster.gif"/>
+                    <attr name="preferencesNode" methodvalue="at.ssw.visualizer.cfg.graph.CfgScene.getPreferences"/>
+                    <attr name="preferencesKey" stringvalue="loopClusters"/>
+                </file>
+                <file name="com-oracle-graal-visualizer-sharedactions-ShowAllAction.shadow">
+                    <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ShowAllAction.instance"/>
+                </file>
+                <file name="com-oracle-graal-visualizer-sharedactions-ZoomInAction.shadow">
+                    <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ZoomInAction.instance"/>
+                </file>
+                <file name="com-oracle-graal-visualizer-sharedactions-ZoomOutAction.shadow">
+                    <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ZoomOutAction.instance"/>
+                </file>
+                <file name="com-oracle-graal-visualizer-sharedactions-ExportSVGAction.shadow">
+                    <attr name="originalFile" stringvalue="Actions/File/com-oracle-graal-visualizer-sharedactions-ExportSVGAction.instance"/>
+                </file>
+            </folder>
+        </folder>
+    </folder>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdge.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,10 @@
+package at.ssw.visualizer.cfg.model;
+
+public interface CfgEdge {
+    public CfgNode getSourceNode();
+    public CfgNode getTargetNode();
+    public boolean isXhandler();
+    public boolean isBackEdge();
+    public boolean isSymmetric();
+    public boolean isReflexive();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdgeImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,50 @@
+package at.ssw.visualizer.cfg.model;
+
+public class CfgEdgeImpl implements CfgEdge {   
+    private CfgNodeImpl sourceNode;
+    private CfgNodeImpl targetNode;
+    private boolean symmetric;
+    private boolean backedge;
+
+    public CfgEdgeImpl(CfgNodeImpl sourceNode, CfgNodeImpl targetNode) {
+        this.sourceNode = sourceNode;
+        this.targetNode = targetNode;
+    }
+   
+    public void setSymmetric(boolean symmetric){
+        this.symmetric = symmetric;
+    }
+    
+    public void setBackEdge(boolean isBackedge){
+        this.backedge = isBackedge;
+    }
+        
+    public CfgNode getSourceNode() {
+        return sourceNode;
+    }
+
+    public CfgNode getTargetNode() {
+        return targetNode;
+    }
+
+    public boolean isBackEdge() {
+        return this.backedge;
+    }
+
+    public boolean isSymmetric() {
+        return symmetric;
+    }
+
+    public boolean isReflexive() {
+        return sourceNode==targetNode;
+    }
+    
+    public boolean isXhandler() {
+        return sourceNode.getBasicBlock().getXhandlers().contains(targetNode.getBasicBlock());
+    }
+
+    @Override
+    public String toString(){
+        return this.sourceNode.getBasicBlock().getName() + "->" + targetNode.getBasicBlock().getName();
+    }  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEnv.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,297 @@
+package at.ssw.visualizer.cfg.model;
+
+import at.ssw.visualizer.model.cfg.BasicBlock;
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+
+/**
+ * This is the container class for the data model,
+ * it prepares creates nodes and edges for the CfgScene
+ * from a ControlFlowGraph of the Compilation Model
+ */
+public class CfgEnv {
+    private ControlFlowGraph cfg;    
+    private Map<CfgNode, LoopInfo> loopMap;//maps: LoopHeader --> LoopInfo
+    private CfgNodeImpl[] nodeArr;
+    private CfgEdgeImpl[] edgeArr;
+       
+    public CfgEnv(ControlFlowGraph cfg) {
+        this.cfg = cfg;        
+        int blockCount = cfg.getBasicBlocks().size();
+        CfgNodeImpl[] nodes = new CfgNodeImpl[blockCount];
+        Map<BasicBlock, CfgNodeImpl> block2nodeMap = new HashMap<>();
+        Map<CfgNodeImpl, Set<CfgEdgeImpl>> inputMap = new HashMap<>();
+        ArrayList<CfgEdgeImpl> allEdges = new ArrayList<>();
+        List<BasicBlock> blocks = cfg.getBasicBlocks();           
+        //create nodes
+        for(int idx=0 ; idx < blockCount ; idx++) {
+            BasicBlock b = blocks.get(idx);
+            
+            String description = "Name: " + b.getName() + "\n";
+            description += "BCI: [" + b.getFromBci() + "," + b.getToBci() + "]\n";
+            if (b.getLoopDepth() > 0) {
+                description += "Loop " + b.getLoopIndex() + " Depth " + b.getLoopDepth() + "\n";
+            }
+            description += "Predecessors: " + getBlockList(b.getPredecessors()) + "\n";
+            description += "Successors: " + getBlockList(b.getSuccessors()) + "\n";
+            description += "XHandlers: " + getBlockList(b.getXhandlers());
+            if (b.getDominator() != null) {
+                description += "\nDominator: " + b.getDominator().getName();
+            } 
+            nodes[idx] = new CfgNodeImpl(b, idx, description);
+            block2nodeMap.put(b, nodes[idx]);
+        }
+        
+        
+        //create edges
+        Set<String> cache = new HashSet<>();//avoids identical edges with same source and same target
+        for(int i = 0 ; i < blockCount ; i++) {
+            BasicBlock b = blocks.get(i);       
+            List<CfgEdgeImpl> outputEdges = new ArrayList<>();           
+            
+            Set<BasicBlock> successors = new HashSet<>();
+            successors.addAll(b.getSuccessors());
+            successors.addAll(b.getXhandlers());
+            for(BasicBlock sb : successors) {  
+                CfgNodeImpl succNode = block2nodeMap.get(sb);
+                CfgEdgeImpl edge = new CfgEdgeImpl(nodes[i], succNode);                
+                if(cache.contains(edge.toString())) 
+                    continue;
+                cache.add(edge.toString());
+                //check for symtric edges              
+                if(sb.getXhandlers().contains(b) || sb.getSuccessors().contains(b)) 
+                    edge.setSymmetric(true);
+                outputEdges.add(edge);                         
+            }
+            allEdges.addAll(outputEdges);
+            nodes[i].setOutputEdges(outputEdges.toArray(new CfgEdgeImpl[outputEdges.size()]));    
+        }
+
+        for(CfgEdgeImpl e: allEdges) {
+            //CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode();
+            CfgNodeImpl tar = (CfgNodeImpl) e.getTargetNode();
+            Set<CfgEdgeImpl> set = inputMap.get(tar);
+            if( set == null) {
+                set = new HashSet<>();      
+                set.add(e);
+                inputMap.put(tar, set);
+            }
+            set.add(e);    
+        }
+        for(CfgNodeImpl n : nodes){
+            Set<CfgEdgeImpl> inputEdges = inputMap.get(n);
+            if(inputEdges == null) continue;
+            n.setInputEdges(inputEdges.toArray(new CfgEdgeImpl[inputEdges.size()]));
+        }    
+        CfgEdgeImpl[] edges = allEdges.toArray(new CfgEdgeImpl[allEdges.size()]);
+        this.edgeArr=edges;
+        this.nodeArr=nodes;       
+        CfgNodeImpl rootNode = nodeArr[0];                   
+        setNodeLevels(rootNode);       
+        indexLoops(rootNode); 
+                          
+    }
+    
+    
+    private String getBlockList(List<? extends BasicBlock> blocks) {
+        if (blocks.size() == 0) {
+            return "None";
+        }
+        StringBuilder sb = new StringBuilder();
+        String prefix = "";
+        for (BasicBlock b : blocks) {
+            sb.append(prefix).append(b.getName());
+            prefix = ", ";
+        }
+        return sb.toString();
+    }
+ 
+    
+    public CfgNode[] getNodes(){
+        return this.nodeArr;
+    }
+    
+    public CfgEdge[] getEdges(){
+        return this.edgeArr;
+    }
+
+    public Map<CfgNode, LoopInfo> getLoopMap() {
+        return loopMap;
+    }
+
+    public void setLoopMap(Map<CfgNode, LoopInfo> loopMap) {
+        this.loopMap = loopMap;
+    }
+ 
+    private void indexLoops(CfgNodeImpl rootNode){
+         LoopEnv env = new LoopEnv(Arrays.asList(nodeArr));
+         loopDetection(env, rootNode);
+         calcLoopDepth(env);      
+                
+         int loopIndex=1;
+          
+         for(LoopInfo info : env.loopMap.values()) {
+             info.setLoopIndex(loopIndex++);
+             info.setLoopDepth(info.getHeader().getLoopDepth());
+             for(CfgNode n : info.getMembers()){
+                if(n.getLoopDepth()>info.getLoopDepth()) continue;
+                CfgNodeImpl ni = (CfgNodeImpl) n;  
+                ni.setLoopDepth(info.getLoopDepth());
+                ni.setLoopIndex(info.getLoopIndex());
+             }
+         }
+         
+         for(LoopInfo info : env.loopMap.values()) {          
+            HashSet<CfgNode> members =  new HashSet<>(info.getMembers());         
+            members.remove(info.getHeader());//remove own header
+            for(CfgNode n: members){              
+                if(n.isLoopHeader()) {                   
+                    LoopInfo memberInfo = env.loopMap.get(n);
+                    if (info.getLoopDepth() == memberInfo.getLoopDepth()-1)
+                        memberInfo.setParent(info);
+                }                    
+            }
+         }
+         this.loopMap = env.loopMap; 
+    }
+
+    
+    private class LoopEnv {   
+        Set<CfgNodeImpl> allNodes;
+        Set<CfgNodeImpl> activeNodes; 
+        Set<CfgNodeImpl> visitedNodes;       
+        Map<CfgNode, LoopInfo> loopMap;
+        private int loopIndex=0;
+        
+        public LoopEnv(Collection<CfgNodeImpl> nodes){
+            allNodes = new HashSet<>(nodes); 
+            activeNodes = new HashSet<>(2 * allNodes.size());
+            visitedNodes = new HashSet<>(2 * allNodes.size());   
+            loopMap = new HashMap<>();
+        }  
+        
+        public int getLoopIndex(){         
+            return ++loopIndex;           
+        }    
+    }
+      
+  
+    private void loopDetection(LoopEnv env, CfgNodeImpl root) {  
+        for (CfgNodeImpl n : env.allNodes) {
+            n.setLoopHeader(false);
+            for (CfgEdge e : n.getInputEdges()) {
+                CfgEdgeImpl ei = (CfgEdgeImpl) e;        
+                ei.setBackEdge(false);       
+            }
+        }
+        visit(env, root, null);
+    }
+   
+
+    
+    private void visit(LoopEnv env, CfgNodeImpl n, CfgEdgeImpl e) {
+        if (env.activeNodes.contains(n)) {
+            // This node is b loop header!
+            n.setLoopHeader(true);
+            e.setBackEdge(true);
+        } else if (!env.visitedNodes.contains(n)) {
+            env.visitedNodes.add(n);
+            env.activeNodes.add(n);
+            
+            for (CfgEdge edge : n.getOutputEdges()) {               
+                if(!edge.getTargetNode().isOSR()) {
+                    CfgEdgeImpl ei = (CfgEdgeImpl) edge;
+                    CfgNodeImpl ni = (CfgNodeImpl) edge.getTargetNode();
+                    visit(env, ni, ei);
+                }
+            }
+            env.activeNodes.remove(n);
+        }
+    }
+    
+    
+    
+    private void calcLoopDepth(LoopEnv env) {
+        for (CfgNodeImpl n : env.allNodes) {
+            env.visitedNodes.clear();
+
+            if (n.isLoopHeader()) {
+                LoopInfo loop = new LoopInfo();
+                loop.setHeader(n);
+                n.setLoopIndex(env.getLoopIndex());
+                HashSet<CfgNode> members = new HashSet<>();
+                loop.setMembers(members);
+                members.add(n);               
+                env.loopMap.put(loop.getHeader(), loop);
+                int loopDepth = n.getLoopDepth() + 1;
+                loop.setLoopDepth(loopDepth);
+                n.setLoopDepth(loopDepth);
+                for (CfgEdge e : n.getInputEdges())  {
+                    if (e.isBackEdge() && !e.getSourceNode().isOSR()) {
+                        CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode();
+                        backwardIteration(env, n, src, loop);               
+                        loop.getBackEdges().add(e);
+                    }
+                }
+            }
+        }
+    }
+  
+
+    private void backwardIteration(LoopEnv env, CfgNodeImpl endNode, CfgNodeImpl n, LoopInfo loop) {
+        if (endNode != n && !env.visitedNodes.contains(n)) {
+            env.visitedNodes.add(n);
+
+            for (CfgEdge e : n.getInputEdges()) {
+                if (!e.getSourceNode().isOSR()) {
+                    CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode();
+                    backwardIteration(env, endNode, src, loop);
+                }
+            }
+            loop.getMembers().add(n); 
+            n.setLoopDepth(n.getLoopDepth() + 1);
+        }
+    }
+    
+    private void setNodeLevels(CfgNode rootNode){
+        Set<CfgNode> cache = new HashSet<>();
+        Queue<CfgNode> queue = new LinkedList<>();
+        queue.add(rootNode);
+        cache.add(rootNode);
+        int level=0;
+        int[] nodeCount = new int[2];
+        nodeCount[0]=1;
+        while(!queue.isEmpty()){           
+            CfgNodeImpl curNode = (CfgNodeImpl) queue.poll();
+            curNode.setLevel(level);                 
+            nodeCount[0]--;       
+            for(CfgEdge outEdge : curNode.getOutputEdges()) {
+                CfgNode succNode = outEdge.getTargetNode();
+                if(cache.contains(succNode)) continue;
+                cache.add(succNode);
+                queue.add(succNode);
+                nodeCount[1]++;
+            }
+            if(nodeCount[0]==0){
+                nodeCount[0]=nodeCount[1];
+                nodeCount[1]=0;
+                level++;
+            }
+        }               
+    }
+
+    public ControlFlowGraph getCfg() {
+        return cfg;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNode.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,23 @@
+package at.ssw.visualizer.cfg.model;
+
+import at.ssw.visualizer.model.cfg.BasicBlock;
+
+
+public interface CfgNode {
+    //testers    
+    public boolean isOSR();
+    public boolean isRoot();
+    public boolean isLoopHeader();
+    public boolean isLoopMember();
+       
+    //getters
+    public int getLevel();
+    public int getLoopDepth();
+    public int getLoopIndex();
+    public int getNodeIndex();
+    public CfgEdge[] getInputEdges();
+    public CfgEdge[] getOutputEdges();
+    public BasicBlock getBasicBlock();
+    public String getDescription();
+   
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNodeImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,133 @@
+package at.ssw.visualizer.cfg.model;
+
+import at.ssw.visualizer.model.cfg.BasicBlock;
+import java.awt.Color;
+
+
+
+public class CfgNodeImpl implements CfgNode {
+    private int nodeIndex;
+    private BasicBlock basicBlock;
+    private int level;   
+    private int loopDepth=0;
+    private int loopIndex=0; 
+    private boolean osr=false;
+    private CfgNodeImpl dominator=null;
+    private CfgEdgeImpl[] inputEdges = new CfgEdgeImpl[0];
+    private CfgEdgeImpl[] outputEdges = new CfgEdgeImpl[0];
+    private String description;
+    private Color customColor=null;
+    private boolean loopHeader;
+       
+    public CfgNodeImpl(BasicBlock bb, int nodeIndex, String description) {
+        this.basicBlock = bb;
+        this.nodeIndex = nodeIndex;  
+        this.description = description;
+        
+        if (bb.getPredecessors().size() == 1) {
+            BasicBlock pred = bb.getPredecessors().get(0);
+            boolean isStd = pred.getPredecessors().size() == 0;
+            if (isStd) {
+                for (String s : bb.getFlags()) {
+                    if (s.equals("osr")) {
+                        osr = true;
+                        break;
+                    }
+                }
+            }
+        }   
+    }
+
+    public int getNodeIndex() {
+        return nodeIndex;
+    }
+    
+    
+    public void setDominator(CfgNodeImpl dominator) {
+        this.dominator = dominator;
+    }
+
+    public void setLevel(int level) {
+        this.level = level;
+    }
+
+    public void setLoopDepth(int loopDepth) {
+        this.loopDepth = loopDepth;
+    }
+
+    public void setLoopHeader(boolean loopHeader) {
+        this.loopHeader = loopHeader;
+    }
+
+    public void setLoopIndex(int loopIndex) {
+        this.loopIndex = loopIndex;
+    }
+
+    public void setNodeIndex(int nodeIndex) {
+        this.nodeIndex = nodeIndex;
+    }
+       
+    public boolean isRoot() {
+        return nodeIndex==0;
+    }
+
+    public boolean isLoopHeader() {
+        return loopHeader;
+    }
+
+    public boolean isLoopMember() {
+        return loopIndex > 0;
+    }
+
+    public int getLevel() {
+        return level;
+    }
+
+    public BasicBlock getBasicBlock() {
+        return basicBlock;
+    }
+    
+    public int getLoopDepth() {
+        return loopDepth;
+    }
+
+    public int getLoopIndex() {
+        return loopIndex;
+    }
+   
+    public boolean isOSR() {
+        return osr;
+    }
+    
+    @Override
+    public String toString(){
+        return basicBlock.getName();
+    }
+
+    public void setInputEdges(CfgEdgeImpl[] inputEdges){
+        this.inputEdges = inputEdges;
+    }
+    
+    
+    public void setOutputEdges(CfgEdgeImpl[] outputEdges){
+        this.outputEdges = outputEdges;
+    }
+     
+    public CfgEdge[] getInputEdges() {
+        return this.inputEdges;
+    }
+
+    public CfgEdge[] getOutputEdges() {
+        return outputEdges;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setColor(Color color) {
+        this.customColor=color;
+    }
+
+   
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/LoopInfo.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,67 @@
+package at.ssw.visualizer.cfg.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+
+public class LoopInfo {  
+    private CfgNode header;//the target node of the backedge
+    private int loopIndex; //index of the min cycleSet
+    private int loopDepth; //nested depth >=1 
+    private LoopInfo parent=null;  
+    private Set<CfgNode> members;
+    private List<CfgEdge> backEdges = new ArrayList<>();//dfs backEdge
+
+    protected void setLoopDepth(int depth) {
+        this.loopDepth=depth;
+    }
+
+    protected void setLoopIndex(int loopIndex) {
+        this.loopIndex = loopIndex;
+    }
+
+    public int getLoopDepth() {
+        return loopDepth;
+    }
+            
+    public Set<CfgNode> getMembers() {
+        return members;
+    }
+
+    protected void setMembers(Set<CfgNode> members) {
+        this.members = members;
+    }
+        
+    public int getLoopIndex() {
+        return loopIndex;
+    }
+
+    protected void setParent(LoopInfo parent) {
+        this.parent = parent;
+    }
+    
+    public LoopInfo getParent(){
+        return parent;
+    }
+    
+    public List<CfgEdge> getBackEdges() {
+        return backEdges;
+    }
+
+    public CfgNode getHeader() {
+        return header;
+    }
+
+    protected void setHeader(CfgNode header) {
+        this.header = header;
+    }
+
+    @Override
+    public String toString(){
+        return "Loop(" + header.toString()+ ")-->" + members.toString();
+    }
+
+    
+  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsCategory.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,32 @@
+package at.ssw.visualizer.cfg.preferences;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import org.netbeans.spi.options.OptionsCategory;
+import org.netbeans.spi.options.OptionsPanelController;
+import org.openide.util.ImageUtilities;
+
+/**
+ * Descriptor for the settings page displayed in the options dialog.
+ *
+ * @author Bernhard Stiftner
+ */
+public class CFGOptionsCategory extends OptionsCategory {
+    
+    public OptionsPanelController create() {
+        return new CFGOptionsPanelController();
+    }
+
+    public String getCategoryName() {
+        return "Control Flow Graph";
+    }
+
+    @Override
+    public Icon getIcon() {
+        return new ImageIcon(ImageUtilities.loadImage("at/ssw/visualizer/cfg/icons/cfg32.gif"));
+    }
+
+    public String getTitle() {
+        return "CFG Visualizer";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanel.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,482 @@
+package at.ssw.visualizer.cfg.preferences;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.AbstractAction;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+
+/**
+ * The actual component for changing the CFG visualizer settings.
+ *
+ * @author Bernhard Stiftner
+ * @author Rumpfhuber Stefan
+ */
+public class CFGOptionsPanel extends JPanel {
+
+    List<ConfigurationElement> elements = new ArrayList<>();
+
+    /** Creates a new instance of CFGOptionsPanel */
+    public CFGOptionsPanel() {
+        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+        JPanel cfgPanel = new JPanel(new GridBagLayout());
+
+        // color/font settings
+        addColorChooser(cfgPanel, "Background color: ", new ColorChooser(CfgPreferences.PROP_BACKGROUND_COLOR){
+            @Override
+            public void apply() {
+                CfgPreferences.getInstance().setBackgroundColor(getColor());              
+            }
+
+            @Override
+            public void update() {
+               this.originalColor = CfgPreferences.getInstance().getBackgroundColor();
+               setColor(this.originalColor);
+            }
+            
+             public void reset() {
+                this.setColor(CfgPreferencesDefaults.DEFAULT_BACKGROUND_COLOR);
+            }
+            
+            
+           
+        });
+        addColorChooser(cfgPanel, "Back edge color: ", new ColorChooser(CfgPreferences.PROP_BACK_EDGE_COLOR){
+
+            @Override
+            public void apply() {               
+                CfgPreferences.getInstance().setBackedgeColor(getColor());                 
+            }
+
+            @Override
+            public void update() {
+                this.originalColor = CfgPreferences.getInstance().getBackedgeColor();
+                this.setColor(this.originalColor);
+
+            }
+
+            public void reset() {
+                this.setColor(CfgPreferencesDefaults.DEFAULT_BACKEDGE_COLOR);
+            }
+        });
+        addColorChooser(cfgPanel, "Edge color: ", new ColorChooser(CfgPreferences.PROP_EDGE_COLOR){
+
+            @Override
+            public void apply() {               
+                CfgPreferences.getInstance().setEdgeColor(getColor());  
+            }
+
+            @Override
+            public void update() {
+                this.originalColor = CfgPreferences.getInstance().getEdgeColor(); 
+                setColor(this.originalColor);
+            }
+            
+            public void reset() {
+                this.setColor(CfgPreferencesDefaults.DEFAULT_EDGE_COLOR);
+            }
+            
+        });
+        addColorChooser(cfgPanel, "Exception edge color: ", new ColorChooser(CfgPreferences.PROP_EXCEPTION_EDGE_COLOR){
+
+            @Override
+            public void apply() {             
+                CfgPreferences.getInstance().setExceptionEdgeColor(getColor());  
+            }
+
+            @Override
+            public void update() {
+                this.originalColor = CfgPreferences.getInstance().getExceptionEdgeColor();
+                setColor(this.originalColor);
+                
+            }
+            
+            public void reset() {
+                this.setColor(CfgPreferencesDefaults.DEFAULT_EXCEPTIONEDGE_COLOR);
+            }
+        });
+        addColorChooser(cfgPanel, "Node color: ", new ColorChooser(CfgPreferences.PROP_NODE_COLOR){
+
+            @Override
+            public void apply() {
+               CfgPreferences.getInstance().setNodeColor(getColor());  
+            }
+
+            @Override
+            public void update() {
+                this.originalColor = CfgPreferences.getInstance().getNodeColor();
+                setColor(this.originalColor);
+                
+            }
+            
+            public void reset() {
+                this.setColor(CfgPreferencesDefaults.DEFAUT_NODE_COLOR);
+            }
+        });
+        addColorChooser(cfgPanel, "Text color: ", new ColorChooser(CfgPreferences.PROP_TEXT_COLOR){
+
+            @Override
+            public void apply() {
+               CfgPreferences.getInstance().setTextColor(getColor());  
+            }
+
+            @Override
+            public void update() {
+               this.originalColor = CfgPreferences.getInstance().getTextColor();
+               
+            }
+            
+            public void reset() {
+                this.setColor(CfgPreferencesDefaults.DEFAULT_TEXT_COLOR);
+            }
+        });     
+        addColorChooser(cfgPanel, "Border color: ", new ColorChooser(CfgPreferences.PROP_BORDER_COLOR){
+
+            @Override
+            public void apply() {
+                CfgPreferences.getInstance().setBorderColor(getColor());  
+            }
+
+            @Override
+            public void update() {
+                this.originalColor = CfgPreferences.getInstance().getBorderColor();
+                setColor(this.originalColor);
+                
+            }
+            public void reset() {
+                this.setColor(CfgPreferencesDefaults.DEFAULT_BORDER_COLOR);
+            }
+        });
+        addColorChooser(cfgPanel, "Selected Nodes color: ", new ColorChooser(CfgPreferences.PROP_SELECTION_COLOR_FG){
+
+            @Override
+            public void apply() {
+                CfgPreferences.getInstance().setSelectionColorForeground(getColor());  
+            }
+
+            @Override
+            public void update() {
+                this.originalColor = CfgPreferences.getInstance().getSelectionColorForeground();
+                setColor(this.originalColor);
+            }
+            
+            public void reset() {
+                this.setColor(CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND);
+            }
+        });
+        addColorChooser(cfgPanel, "Selection Rect color: ", new ColorChooser(CfgPreferences.PROP_SELECTION_COLOR_BG){
+
+            @Override
+            public void apply() {
+                CfgPreferences.getInstance().setSelectionColorBackground(getColor());
+            }
+
+            @Override
+            public void update() {
+                this.originalColor = CfgPreferences.getInstance().getSelectionColorBackground();
+                setColor(this.originalColor);
+            }
+            
+            public void reset() {
+                this.setColor(CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_BACKGROUND);
+            }
+        });
+        addFontChooser(cfgPanel, "Text font: ", new FontChooser(CfgPreferences.PROP_TEXT_FONT){
+
+            @Override
+            public void apply() {
+                CfgPreferences.getInstance().setTextFont(getSelectedFont());                
+            }
+
+            @Override
+            public void update() {
+                this.originalFont = CfgPreferences.getInstance().getTextFont();
+                this.setSelectedFont(originalFont);
+                
+            }
+            
+            public void reset() {
+                this.setSelectedFont(CfgPreferencesDefaults.DEFAULT_TEXT_FONT);
+            }
+        });
+
+        // flags editor
+        addFlagsEditor(cfgPanel, "Flags: ");
+        add(cfgPanel);
+
+        // add update button
+        Box hBox = new Box(BoxLayout.X_AXIS);
+        hBox.add(new JButton(new ResetAction()));
+        hBox.add(Box.createHorizontalGlue());
+        add(hBox);
+
+        add(Box.createVerticalGlue());
+    }
+    
+    public void update() {
+        for (ConfigurationElement e : elements) {          
+            e.update();
+        }
+    }
+
+    public void cancel() {
+        for (ConfigurationElement e : elements) {
+            e.update();
+        }
+    }
+
+    public void applyChanges() {
+        for (ConfigurationElement e : elements) {
+            if(e.isChanged())
+                e.apply();
+        }
+    }
+
+    public boolean isDataValid() {
+        return true;
+    }
+
+    public boolean isChanged() {
+        for (ConfigurationElement e : elements) {
+            if (e.isChanged()) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    public void loadDefault() {
+        for (ConfigurationElement e : elements) {
+            e.reset();
+        }
+    }
+
+    private void addColorChooser(JComponent c, String displayName, ColorChooser chooser) {
+        GridBagLayout layout = (GridBagLayout)c.getLayout();
+        GridBagConstraints constraints = new GridBagConstraints();
+        constraints.insets = new Insets(3, 3, 3, 3);
+        constraints.weightx = 0.0;
+        constraints.fill = GridBagConstraints.NONE;
+        constraints.anchor = GridBagConstraints.EAST;
+        JLabel label = new JLabel(displayName, JLabel.TRAILING);
+        layout.setConstraints(label, constraints);
+        c.add(label);
+        constraints.anchor = GridBagConstraints.WEST;
+        constraints.gridwidth = GridBagConstraints.REMAINDER;
+        layout.setConstraints(chooser, constraints);
+        c.add(chooser);
+        elements.add(chooser);
+        label.setLabelFor(chooser);
+    }
+
+   
+
+    private void addFontChooser(JComponent c, String displayName, FontChooser chooser) {
+        GridBagLayout layout = (GridBagLayout)c.getLayout();
+        GridBagConstraints constraints = new GridBagConstraints();
+        constraints.insets = new Insets(3, 3, 3, 3);
+        constraints.weightx = 0.0;
+        constraints.fill = GridBagConstraints.NONE;
+        constraints.anchor = GridBagConstraints.EAST;
+        JLabel label = new JLabel(displayName, JLabel.TRAILING);
+        layout.setConstraints(label, constraints);
+        c.add(label);
+        constraints.insets = new Insets(3, 3, 3, 1);
+        constraints.weightx = 1.0;
+        constraints.fill = GridBagConstraints.HORIZONTAL;
+        constraints.anchor = GridBagConstraints.CENTER;
+        layout.setConstraints(chooser.getPreview(), constraints);
+        c.add(chooser.getPreview());
+        constraints.insets = new Insets(3, 1, 3, 3);
+        constraints.weightx = 0.0;
+        constraints.fill = GridBagConstraints.NONE;
+        constraints.anchor = GridBagConstraints.EAST;
+        constraints.gridwidth = GridBagConstraints.REMAINDER;
+        layout.setConstraints(chooser.getButton(), constraints);
+        c.add(chooser.getButton());
+        elements.add(chooser);
+        label.setLabelFor(chooser.getButton());
+    }
+
+    private void addFlagsEditor(JComponent c, String displayName) {
+        GridBagLayout layout = (GridBagLayout)c.getLayout();
+        GridBagConstraints constraints = new GridBagConstraints();
+        constraints.insets = new Insets(3, 3, 3, 3);
+        constraints.weightx = 0.0;
+        constraints.fill = GridBagConstraints.NONE;
+        constraints.anchor = GridBagConstraints.NORTHEAST;
+        FlagsEditor flagsEditor = new FlagsEditor();
+        JLabel flagsLabel = new JLabel(displayName, JLabel.TRAILING);
+        flagsLabel.setVerticalAlignment(SwingConstants.TOP);
+        layout.setConstraints(flagsLabel, constraints);
+        c.add(flagsLabel);
+        constraints.weightx = 1.0;
+        constraints.weighty = 1.0;
+        constraints.fill = GridBagConstraints.BOTH;
+        constraints.anchor = GridBagConstraints.CENTER;
+        constraints.gridwidth = GridBagConstraints.REMAINDER;
+        layout.setConstraints(flagsEditor, constraints);
+        c.add(flagsEditor);
+        elements.add(flagsEditor);
+        flagsLabel.setLabelFor(flagsEditor);
+    }
+
+    
+    
+
+    interface ConfigurationElement {
+
+        public boolean isChanged();
+        
+        //apply changes to preferences
+        public void apply();
+        
+        //optain current value from preferences
+        public void update();
+        
+        //reset to default value
+        public void reset();
+        
+    }
+    
+    abstract class ColorChooser extends ColorChooserButton implements ConfigurationElement {
+
+        Color originalColor;//the color before any change
+        String propertyName;
+
+        public ColorChooser(String propertyName) {
+            this.propertyName = propertyName;
+        }
+        
+        public boolean isChanged() {
+            return !originalColor.equals(getColor());
+        }
+        
+        
+        public abstract void apply();
+        public abstract void update();
+
+    }
+    
+
+    abstract class FontChooser implements ConfigurationElement, ActionListener {
+
+        Font originalFont;
+        Font selectedFont;
+        String propertyName;
+        JTextField preview;
+        JButton button;
+
+        public FontChooser(String propertyName) {
+            this.propertyName = propertyName;
+            preview = new JTextField("");
+            preview.setEditable(false);
+            button = new JButton("...");
+            button.setMargin(new Insets(0, 0, 0, 0));
+            button.addActionListener(this);
+        }
+
+        public boolean isChanged() {
+            return !originalFont.equals(selectedFont);
+        }
+        
+        public abstract void apply();
+        
+        public abstract void update();
+        
+        public abstract void reset();
+
+        public JTextField getPreview() {
+            return preview;
+        }
+
+        public JButton getButton() {
+            return button;
+        };
+
+        public Font getSelectedFont() {
+            return selectedFont;
+        }
+
+        public void setSelectedFont(Font f) {
+            selectedFont = f;
+            preview.setText(fontToString(f));
+            preview.revalidate();
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            setSelectedFont(FontChooserDialog.show(selectedFont));
+        }
+
+        public String fontToString(Font font) {
+            StringBuffer sb = new StringBuffer();
+            sb.append(font.getName());
+            sb.append(" ");
+            sb.append(font.getSize());
+            if (font.isBold()) {
+                sb.append(" bold");
+            }
+            if (font.isItalic()) {
+                sb.append(" italic");
+            }
+            return sb.toString();
+        }
+
+    }
+
+    class FlagsEditor extends FlagsEditorPanel implements ConfigurationElement {
+
+        FlagsSetting originalFlags;
+
+        public FlagsEditor() {
+            super(null);    
+        }
+
+        public boolean isChanged() {
+            return !originalFlags.getFlagString().equals(getFlagString());
+        }
+
+        public void apply() {
+            CfgPreferences.getInstance().setFlagsSetting(new FlagsSetting(getFlagString()));
+            update();
+        }
+
+        public void update() {
+            originalFlags = CfgPreferences.getInstance().getFlagsSetting();
+            setFlagString(originalFlags.getFlagString());
+        }
+
+        public void reset() {
+            FlagsSetting defaultFlags = new FlagsSetting(CfgPreferencesDefaults.DEFAULT_FLAGSTRING);
+            setFlagString(defaultFlags.getFlagString());
+            colorButton.setColor(getParent().getBackground());            
+        }
+
+    }
+
+    class ResetAction extends AbstractAction {
+
+        public ResetAction() {
+            super("Reset");
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            CFGOptionsPanel.this.loadDefault();           
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanelController.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,63 @@
+package at.ssw.visualizer.cfg.preferences;
+
+import java.beans.PropertyChangeListener;
+import javax.swing.JComponent;
+import org.netbeans.spi.options.OptionsPanelController;
+import org.openide.util.HelpCtx;
+import org.openide.util.Lookup;
+
+/**
+ * Controller for the settings page displayed in the options dialog.
+ *
+ * @author Bernhard Stiftner
+ */
+public class CFGOptionsPanelController extends OptionsPanelController {
+
+    CFGOptionsPanel optionsPanel;
+
+    
+    public void update() {
+        getOptionsPanel().update();       
+    }
+
+    public void applyChanges() {
+        getOptionsPanel().applyChanges();
+    }
+
+    public void cancel() {
+        getOptionsPanel().cancel();
+    }
+
+    public boolean isValid() {
+        return getOptionsPanel().isDataValid();
+    }
+
+    public boolean isChanged() {
+        return getOptionsPanel().isChanged();
+    }
+
+    public JComponent getComponent(Lookup masterLookup) {
+        return getOptionsPanel();
+    }
+
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+    
+    public void addPropertyChangeListener(PropertyChangeListener l) {
+        getOptionsPanel().addPropertyChangeListener(l);
+    }
+
+    //todo: investigate - who removes the changelistener ?
+    public void removePropertyChangeListener(PropertyChangeListener l) {
+        getOptionsPanel().removePropertyChangeListener(l);
+    }
+
+    private CFGOptionsPanel getOptionsPanel() {
+        if (optionsPanel == null) {
+            optionsPanel = new CFGOptionsPanel();
+        }
+        return optionsPanel;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferences.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,239 @@
+package at.ssw.visualizer.cfg.preferences;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.prefs.Preferences;
+import javax.swing.event.EventListenerList;
+import org.openide.util.NbPreferences;
+
+/**
+ * Replacement for old CFGSettings to remove dependency on deprecated SystemOption package
+ * 
+ * @author Rumpfhuber Stefan
+ */
+public class CfgPreferences  {
+    public static final String PROP_FLAGS = "flagsPreference";
+    public static final String PROP_TEXT_FONT = "textFontPreference";
+    public static final String PROP_TEXT_COLOR = "textColorPreference";
+    public static final String PROP_NODE_COLOR = "nodeColorPreference";
+    public static final String PROP_EDGE_COLOR = "edgeColorPreference";
+    public static final String PROP_BORDER_COLOR = "borderColorPreference";
+    public static final String PROP_BACK_EDGE_COLOR = "backEdgeColorPreference";
+    public static final String PROP_BACKGROUND_COLOR = "backgroundColorPreference";
+    public static final String PROP_SELECTION_COLOR_FG = "selectionColorFgPreference";
+    public static final String PROP_SELECTION_COLOR_BG = "selectionColorBgPreference";
+    public static final String PROP_EXCEPTION_EDGE_COLOR = "exceptionEdgeColorPreference";
+    
+    private static final String PROP_FONTNAME = "_FontFamily";
+    private static final String PROP_FONTSIZE = "_FontSize";
+    private static final String PROP_FONTSTYLE = "_FontStyle";
+    
+    protected static final String nodeName = "CfgPreferences";
+      
+    private static CfgPreferences instance = new CfgPreferences();
+    private EventListenerList listenerList;
+       
+    private FlagsSetting flagsSetting;
+    private Color node_color; 
+    private Color background_color; 
+    private Color backedge_color; 
+    private Color edge_color;
+    private Color border_color;
+    private Color exceptionEdgeColor;
+    private Color text_color;
+    private Font  text_font;
+    private Color selection_color_fg;
+    private Color selection_color_bg;
+    
+    
+    private  CfgPreferences(){        
+        listenerList = new EventListenerList();       
+        init();           
+    }
+    
+    public static CfgPreferences getInstance(){
+        return instance;
+    }
+
+    protected final Preferences getPreferences() {
+        return NbPreferences.forModule(this.getClass()).node("options").node(nodeName);
+    }
+    
+    
+    protected void init(){
+        Preferences prefs = this.getPreferences();
+        String flagString = prefs.get(PROP_FLAGS, CfgPreferencesDefaults.DEFAULT_FLAGSTRING);
+        flagsSetting = new FlagsSetting(flagString);
+        node_color = this.getColorProperty(PROP_NODE_COLOR, CfgPreferencesDefaults.DEFAUT_NODE_COLOR);
+        background_color = this.getColorProperty(PROP_BACKGROUND_COLOR, CfgPreferencesDefaults.DEFAULT_BACKGROUND_COLOR); 
+        backedge_color = this.getColorProperty(PROP_BACK_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_BACKEDGE_COLOR); 
+        edge_color = this.getColorProperty(PROP_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_EDGE_COLOR);
+        selection_color_fg= this.getColorProperty(PROP_SELECTION_COLOR_FG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND);
+        border_color = this.getColorProperty(PROP_BORDER_COLOR, CfgPreferencesDefaults.DEFAULT_BORDER_COLOR);
+        exceptionEdgeColor = this.getColorProperty(PROP_EXCEPTION_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_EXCEPTIONEDGE_COLOR);
+        text_color= this.getColorProperty(PROP_TEXT_COLOR, CfgPreferencesDefaults.DEFAULT_TEXT_COLOR);
+        selection_color_bg = this.getColorProperty(PROP_SELECTION_COLOR_BG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_BACKGROUND);
+        selection_color_fg = this.getColorProperty(PROP_SELECTION_COLOR_FG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND);
+        text_font = this.getFontProperty(PROP_TEXT_FONT, CfgPreferencesDefaults.DEFAULT_TEXT_FONT);     
+    }
+         
+    private void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
+        Object[] listeners = listenerList.getListenerList();   
+       
+        PropertyChangeEvent event = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
+        for (int i = listeners.length - 2; i >= 0; i -= 2) {
+            if (listeners[i] == PropertyChangeListener.class) {
+                ((PropertyChangeListener) listeners[i+1]).propertyChange(event);
+            }
+        }
+    }
+    
+    private Font getFontProperty(String propName, Font defaultFont){
+        Preferences prefs = this.getPreferences();
+        String fontName = prefs.get(propName+PROP_FONTNAME, defaultFont.getFamily());
+        int fontSize = prefs.getInt(propName+PROP_FONTSIZE, defaultFont.getSize());
+        int fontStyle = prefs.getInt(propName+PROP_FONTSTYLE, defaultFont.getStyle());                
+        return new Font(fontName, fontStyle, fontSize);   
+    }
+       
+    private Color getColorProperty(String propName, Color defaultColor){
+        Preferences prefs = this.getPreferences();
+        int srgb = prefs.getInt(propName, defaultColor.getRGB());
+        if(srgb == defaultColor.getRGB())
+            return defaultColor;
+        return new Color(srgb);
+    }
+     
+    public Color getBackedgeColor() {
+        return backedge_color;
+    }
+  
+    public Color getBackgroundColor() {
+        return background_color;
+    }
+
+    public Color getBorderColor() {
+        return border_color;
+    }
+ 
+    public Color getEdgeColor() {
+        return edge_color;
+    }
+
+    public Color getExceptionEdgeColor() {
+        return exceptionEdgeColor;
+    }
+   
+    public Color getNodeColor() {
+        return node_color;
+    }
+
+    public Color getSelectionColorForeground() {
+        return selection_color_fg;
+    }
+    
+    public Color getSelectionColorBackground() {
+        return selection_color_bg;
+    }
+
+    public Color getTextColor() {
+        return text_color;
+    }
+
+    public Font getTextFont() {
+        return text_font;
+    }
+
+    public FlagsSetting getFlagsSetting() {
+        return flagsSetting;
+    }
+    
+    
+    public void setFlagsSetting(FlagsSetting flagsSetting) {
+        FlagsSetting old = this.getFlagsSetting();
+        this.flagsSetting = flagsSetting;
+        Preferences prefs = getPreferences();
+        firePropertyChange(PROP_FLAGS, old, flagsSetting);
+        prefs.put(PROP_FLAGS, flagsSetting.getFlagString());
+    }
+    
+
+    public void setTextFont(Font text_font) {
+        Font old = this.getTextFont();
+        Preferences prefs = getPreferences();
+        this.text_font = text_font;
+        firePropertyChange(PROP_TEXT_FONT, old, text_font);
+        prefs.put(PROP_TEXT_FONT + PROP_FONTNAME , text_font.getFamily());
+        prefs.putInt(PROP_TEXT_FONT + PROP_FONTSIZE, text_font.getSize());
+        prefs.putInt(PROP_TEXT_FONT + PROP_FONTSTYLE, text_font.getStyle());   
+    }
+    
+   public void setBackedgeColor(Color backedge_color) {
+        Color old = this.getBackedgeColor();        
+        this.backedge_color = backedge_color;
+        firePropertyChange(PROP_BACK_EDGE_COLOR, old, backedge_color);
+        getPreferences().putInt(PROP_BACK_EDGE_COLOR, backedge_color.getRGB());        
+    }
+
+    public void setBackgroundColor(Color bg_color) {
+        Color old = this.getBackgroundColor();
+        background_color = bg_color;
+        firePropertyChange(PROP_BACKGROUND_COLOR, old, bg_color );
+        getPreferences().putInt(PROP_BACKGROUND_COLOR, bg_color.getRGB());      
+    }
+
+    public void setBorderColor(Color border_color) {
+        Color old = getBorderColor();      
+        this.border_color = border_color;
+        firePropertyChange(PROP_BORDER_COLOR, old, border_color );
+        getPreferences().putInt(PROP_BORDER_COLOR, border_color.getRGB());       
+    }
+
+    public void setEdgeColor(Color edge_color) {
+        Color old = getEdgeColor();     
+        this.edge_color = edge_color;
+        firePropertyChange(PROP_EDGE_COLOR, old, edge_color);
+        getPreferences().putInt(PROP_EDGE_COLOR, edge_color.getRGB());      
+    }
+    
+    public void setNodeColor(Color node_color) {
+        Color old = getNodeColor();      
+        this.node_color = node_color;
+        firePropertyChange(PROP_NODE_COLOR, old, node_color);
+        getPreferences().putInt(PROP_NODE_COLOR, node_color.getRGB());
+        
+    }
+    
+    public void setSelectionColorForeground(Color selection_color) {
+         Color old = this.getSelectionColorForeground();   
+         this.selection_color_fg = selection_color;
+         firePropertyChange(PROP_SELECTION_COLOR_FG, old, selection_color);
+         getPreferences().putInt(PROP_SELECTION_COLOR_FG, selection_color.getRGB());       
+    }
+    
+    public void setSelectionColorBackground(Color selection_color) {
+         Color old = this.getSelectionColorBackground();   
+         this.selection_color_bg = selection_color;
+         firePropertyChange(PROP_SELECTION_COLOR_BG, old, selection_color);
+         getPreferences().putInt(PROP_SELECTION_COLOR_BG, selection_color.getRGB());       
+    }
+    
+    public void setTextColor(Color text_color) {
+         Color old = this.getTextColor();       
+         this.text_color = text_color;
+         firePropertyChange(PROP_TEXT_COLOR, old, text_color);
+         getPreferences().putInt(PROP_TEXT_COLOR, text_color.getRGB());     
+    }
+    
+    public void setExceptionEdgeColor(Color exceptionEdgeColor) {
+        Color old = this.getExceptionEdgeColor();  
+        this.exceptionEdgeColor = exceptionEdgeColor;
+        firePropertyChange(PROP_EXCEPTION_EDGE_COLOR, old, exceptionEdgeColor);
+        getPreferences().putInt(PROP_EXCEPTION_EDGE_COLOR, exceptionEdgeColor.getRGB());       
+    }
+
+   
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferencesDefaults.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,23 @@
+package at.ssw.visualizer.cfg.preferences;
+
+import java.awt.Color;
+import java.awt.Font;
+
+/**
+ * Default Configuration for options panel
+ * 
+ * @author Rumpfhuber Stefan
+ */
+public final class CfgPreferencesDefaults {    
+    public static final String DEFAULT_FLAGSTRING = "std(224,224,128);osr(224,224,0);ex(128,128,224);sr(128,224,128);llh(224,128,128);lle(224,192,192);plh(128,224,128);bb(160,0,0);ces(192,192,192)";
+    public static final Color DEFAUT_NODE_COLOR = new Color(208, 208, 208);
+    public static final Color DEFAULT_BACKGROUND_COLOR =  new Color(255, 255, 255);
+    public static final Color DEFAULT_BACKEDGE_COLOR = new Color(160, 0, 0);
+    public static final Color DEFAULT_EDGE_COLOR = new Color(0, 0, 0);
+    public static final Color DEFAULT_SELECTION_COLOR_FOREGROUND = Color.BLUE;
+    public static final Color DEFAULT_SELECTION_COLOR_BACKGROUND = Color.BLUE;
+    public static final Color DEFAULT_BORDER_COLOR = new Color(0, 0, 0);
+    public static final Color DEFAULT_EXCEPTIONEDGE_COLOR = new Color(0, 0, 160);
+    public static final Color DEFAULT_TEXT_COLOR = new Color(0, 0, 0);
+    public static final Font  DEFAULT_TEXT_FONT = new Font("Dialog", Font.PLAIN, 18);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/ColorChooserButton.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,94 @@
+package at.ssw.visualizer.cfg.preferences;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JColorChooser;
+
+/**
+ * A color selection button. It will preview the currently selected color as
+ * an icon. Clicking the button will bring up the JColorChooser dialog.
+ *
+ * @author Bernhard Stiftner
+ */
+public class ColorChooserButton extends JButton implements ActionListener {
+
+    public static final Dimension ICON_SIZE = new Dimension(24, 8);
+
+    Color color;
+    boolean colorChooserEnabled = true; // bring up dialog when clicked?
+
+
+    public ColorChooserButton() {
+        this(Color.black);
+    }
+
+    public ColorChooserButton(Color defaultColor) {
+        setIcon(new ColorBoxIcon());
+        addActionListener(this);
+        color = defaultColor;
+        Dimension size = new Dimension(ICON_SIZE);
+        size.width += getInsets().left + getInsets().right;
+        size.height += getInsets().top + getInsets().bottom;
+        setPreferredSize(size);
+    }
+
+    public void setColor(Color newColor) {
+        color = newColor;
+        repaint();
+    }
+
+    public Color getColor() {
+        return color;
+    }
+
+    public boolean isColorChooserEnabled() {
+        return colorChooserEnabled;
+    }
+
+    public void setColorChooserEnabled(boolean enabled) {
+        this.colorChooserEnabled = enabled;
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        if (!colorChooserEnabled) {
+            return;
+        }
+
+        Color c = JColorChooser.showDialog(this, "Choose color", color);
+        if (c != null) {
+            setColor(c);
+        }
+    }
+
+    class ColorBoxIcon implements Icon {
+
+        public int getIconWidth() {
+            return ICON_SIZE.width;
+        }
+
+        public int getIconHeight() {
+            return ICON_SIZE.height;
+        }
+
+        public void paintIcon(Component c, Graphics g, int x, int y) {
+            Color oldColor = g.getColor();
+            g.translate(x, y);
+
+            g.setColor(color);
+            g.fillRect(0, 0, ICON_SIZE.width, ICON_SIZE.height);
+
+            g.setColor(Color.black);
+            g.drawRect(0, 0, ICON_SIZE.width, ICON_SIZE.height);
+
+            g.translate(-x, -y);
+            g.setColor(oldColor);
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsEditorPanel.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,247 @@
+package at.ssw.visualizer.cfg.preferences;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JColorChooser;
+import javax.swing.JComponent;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+/**
+ *
+ * @author Bernhard Stiftner
+ * @author Rumpfhuber Stefan
+ */
+public class FlagsEditorPanel extends JPanel implements ActionListener,
+        ListSelectionListener {
+
+    FlagListModel listModel;
+    JList list;
+    ColorChooserButton colorButton;
+    JButton newButton;
+    JButton removeButton;
+    JButton upButton;
+    JButton downButton;
+
+
+    /** Creates a new instance of FlagsEditorPanel */
+    public FlagsEditorPanel(String flagString) {
+        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
+
+        listModel = new FlagListModel(flagString);
+        list = new JList(listModel);
+        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        list.addListSelectionListener(this);
+        add(new JScrollPane(list));
+
+        add(Box.createHorizontalStrut(3));
+
+        Box buttonBox = new Box(BoxLayout.Y_AXIS);
+        buttonBox.add(colorButton = new ColorChooserButton());
+        buttonBox.add(newButton = new JButton("New..."));
+        buttonBox.add(removeButton = new JButton("Remove"));
+        buttonBox.add(upButton = new JButton("Up"));
+        buttonBox.add(downButton = new JButton("Down"));
+        buttonBox.add(Box.createVerticalGlue());
+        add(buttonBox);
+        layoutButtonContainer(buttonBox);
+
+        colorButton.setColorChooserEnabled(false);
+        colorButton.addActionListener(this);
+        newButton.addActionListener(this);
+        removeButton.addActionListener(this);
+        upButton.addActionListener(this);
+        downButton.addActionListener(this);
+
+        selectionChanged(-1); // no selection
+    }
+
+    /**
+     * Ugly helper to make a nice layout for vertically aligned buttons.
+     */
+    private static void layoutButtonContainer(JComponent buttonContainer) {
+        int width = 0;
+        int height = 0;
+
+        for (int i=0; i<buttonContainer.getComponentCount(); i++) {
+            Component c = buttonContainer.getComponent(i);
+            if (c instanceof JButton) {
+                JButton b = (JButton)c;
+                if (width < b.getPreferredSize().width) {
+                    width = b.getPreferredSize().width;
+                }
+                if (height < b.getPreferredSize().height) {
+                    height = b.getPreferredSize().height;
+                }
+            }
+        }
+
+        Dimension commonButtonSize = new Dimension(width, height);
+
+        for (int i=0; i<buttonContainer.getComponentCount(); i++) {
+            Component c = buttonContainer.getComponent(i);
+            if (c instanceof JButton) {
+                JButton b = (JButton)c;
+                b.setMinimumSize(commonButtonSize);
+                b.setPreferredSize(commonButtonSize);
+                b.setMaximumSize(commonButtonSize);
+            }
+        }
+
+    }
+
+    public String getFlagString() {
+        return listModel.getFlagString();
+    }
+
+    public void setFlagString(String flagString) {
+        listModel.setFlagString(flagString);
+    }
+    
+    public void actionPerformed(ActionEvent e) {
+        Object source = e.getSource();
+        if (source == colorButton) {
+            changeColor();
+        } else if (source == newButton) {
+            String s = JOptionPane.showInputDialog(this,
+                    "Type in the flag which should fill the block with a specific color");
+            if (s == null) {
+                return;
+            }
+            s = s.replace('(', ' ');
+            s = s.replace(';', ' ');
+            int index = list.getSelectedIndex()+1;
+            listModel.insertElementAt(new FlagListItem(s, Color.WHITE), index);
+        } else if (source == removeButton) {
+            listModel.removeElementAt(list.getSelectedIndex());
+        } else if (source == upButton) {
+            int index = list.getSelectedIndex();
+            if (index == 0) {
+                return;
+            }
+            Object o = listModel.getElementAt(index);
+            listModel.removeElementAt(index);
+            listModel.insertElementAt(o, index-1);
+        } else if (source == downButton) {
+            int index = list.getSelectedIndex();
+            if (index >= listModel.size()-1) {
+                return;
+            }
+            Object o = listModel.getElementAt(index);
+            listModel.removeElementAt(index);
+            listModel.insertElementAt(o, index+1);  
+        }
+    }
+
+    public void valueChanged(ListSelectionEvent e) {
+        if (e.getValueIsAdjusting()) {
+            return; // another event will be fired soon
+        }
+        selectionChanged(list.getSelectedIndex());
+    }
+
+    protected void selectionChanged(int index) { //index is -1 if there is no selection           
+        colorButton.setEnabled(index >= 0);
+        removeButton.setEnabled(index >= 0);
+        upButton.setEnabled(index > 0);
+        downButton.setEnabled(index >= 0 && index < listModel.getSize()-1);
+
+        if (index >= 0) {
+            FlagListItem item = (FlagListItem)listModel.elementAt(index);
+            colorButton.setColor(item.getColor());
+            list.setSelectedIndex(index);
+        } else {
+            colorButton.setColor(getBackground());
+        }
+    }
+
+    protected void changeColor() {
+        int selectedIndex = list.getSelectedIndex();
+        FlagListItem item = (FlagListItem)listModel.elementAt(selectedIndex);
+        Color c = JColorChooser.showDialog(this, "Choose color", item.getColor());
+
+        if (c != null) {
+            item.setColor(c);
+            colorButton.setColor(c);
+        }
+    }
+
+    class FlagListModel extends DefaultListModel {
+
+        public FlagListModel(String flagString) {
+            if (flagString != null) {
+                setFlagString(flagString);
+            }
+        }
+
+        public String getFlagString() {
+            StringBuffer sb = new StringBuffer();
+            Enumeration e = elements();
+            while (e.hasMoreElements()) {
+                FlagListItem item = (FlagListItem)e.nextElement();
+                sb.append(item.getFlagString());
+                Color c = item.getColor();
+                sb.append("(").append(c.getRed()).append(",").append(c.getGreen()).append(",").append(c.getBlue()).append(")");
+                if (e.hasMoreElements()) {
+                    sb.append(";");
+                }
+            }
+            return sb.toString();
+        }
+
+        public void setFlagString(String flagString) {
+            clear();
+            StringTokenizer st = new StringTokenizer(flagString, ";");
+            while (st.hasMoreTokens()) {
+                String s = st.nextToken();
+                String flag = s.split("\\(")[0];
+                Color color = FlagsSetting.toColor(s);
+                addElement(new FlagListItem(flag, color));
+            }
+        }
+
+    }
+
+    class FlagListItem {
+
+        Color color;
+        String flagString;
+
+        public FlagListItem(String flagString, Color color) {
+            this.flagString = flagString;
+            this.color = color;
+        }
+
+        public Color getColor() {
+            return color;
+        }
+
+        public String getFlagString() {
+            return flagString;
+        }
+
+        public void setColor(Color c) {
+            color = c;
+        }
+
+        @Override
+        public String toString() {
+            return flagString;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsSetting.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,85 @@
+package at.ssw.visualizer.cfg.preferences;
+
+import java.awt.Color;
+import java.io.Serializable;
+import java.util.Hashtable;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class FlagsSetting implements Serializable {
+
+    private Hashtable<String, Color> flag2color;
+    private Hashtable<String, Integer> priority;
+    private String flagString;
+
+
+    public FlagsSetting(String flagString) {
+        this.flagString = flagString;
+        flag2color = new Hashtable<>();
+        priority = new Hashtable<>();
+        String[] flags = flagString.split(";");
+
+        int z = 0;
+        for(String s : flags) {
+            String flag = s.split("\\(")[0];
+            Color c = toColor(s);
+            flag2color.put(flag, c);
+            priority.put(flag, z);
+            z++;
+        }
+    }
+
+    public Color getColor(List<String> strings) {
+        int minPriority = Integer.MAX_VALUE;
+        Color result = null;
+
+        for(String s : strings) {
+            Color curColor = flag2color.get(s);
+            if(curColor != null) {
+                int curPriority = priority.get(s);
+                if(curPriority < minPriority) {
+                    minPriority = curPriority;
+                    result = curColor;
+                }
+            }
+        }
+
+        return result;
+    }
+
+    public static Color toColor(String s) {
+        String sArr[] = s.split("\\(");
+        String Color = sArr[1].substring(0, sArr[1].length() - 1);
+        String ColorArr[] = Color.split(",");
+        int r = Integer.parseInt(ColorArr[0]);
+        int g = Integer.parseInt(ColorArr[1]);
+        int b = Integer.parseInt(ColorArr[2]);
+        return new Color(r, g, b);
+    }
+
+    public String getFlagString() {
+        return flagString;
+    }
+      
+    @Override
+    public boolean equals(Object o) {
+        if(o==null) 
+            return false;
+        return this.toString().equals(o.toString());
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 7;
+        hash = 19 * hash + (this.flagString != null ? this.flagString.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public String toString(){
+        return "FlagSetting[" + flagString + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FontChooserDialog.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,37 @@
+package at.ssw.visualizer.cfg.preferences;
+
+import java.awt.Font;
+import java.beans.PropertyEditor;
+import java.beans.PropertyEditorManager;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+
+/**
+ *
+ * @author Bernhard Stiftner
+ */
+public class FontChooserDialog {
+
+    /*
+     * Displays a font selection dialog.
+     * @return The selected font, or the initial font if the user chose
+     * to bail out
+     */
+    public static Font show(Font initialFont) {
+        PropertyEditor pe = PropertyEditorManager.findEditor(Font.class);
+        if (pe == null) {
+            throw new RuntimeException("Could not find font editor component.");
+        }
+        pe.setValue(initialFont);
+        DialogDescriptor dd = new DialogDescriptor(
+                pe.getCustomEditor(),
+                "Choose Font");
+        DialogDisplayer.getDefault().createDialog(dd).setVisible(true);
+        if (dd.getValue() == DialogDescriptor.OK_OPTION) {
+            Font f = (Font)pe.getValue();
+            return f;
+        }
+        return initialFont;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/BezierWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,345 @@
+package at.ssw.visualizer.cfg.visual;
+
+import org.netbeans.api.visual.widget.ConnectionWidget;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.util.List;
+import org.netbeans.api.visual.anchor.AnchorShape;
+import org.netbeans.api.visual.graph.GraphScene;
+import org.netbeans.api.visual.widget.Scene;
+import org.netbeans.api.visual.widget.Widget;
+
+
+/**
+ *  In comparison to the default ConnectionWidget this class is able to connect 
+ *  Widgets with a curve instead of a straight line sequence. Between two control
+ *  points a curve is painted as cubic bezier curve the control points are 
+ *  calculated automaticaly they depend on the position of the prior- and the 
+ *  following control points.
+ *  In conjunction with a suitable router the connection will be a straight line 
+ *  or a curve depending on the amount and the position of the controlpoints. 
+ *  Controlpoints supplied by the router, are treated as curve intersection points.
+ *  For Reflexive edges the router doesn`t  need to supply controlpoints, they 
+ *  get painted by this class automatically. If the router supplys more as 2 
+ *  control points for a recursive edge the edge gets painted with the default
+ *  curve approximation algorithm.
+ */
+public class BezierWidget extends ConnectionWidget {
+    private static final double BEZIER_SCALE = 0.3;     
+    private static final double ENDPOINT_DEVIATION = 3;//curve endpoint approximation accuracy
+   
+    private GraphScene scene=null;
+ 
+    public BezierWidget(Scene scene) {
+        super(scene);          
+    }
+    
+    public BezierWidget(GraphScene scene) {
+        super(scene);   
+        this.scene=scene;        
+    }
+ 
+    
+    private boolean isReflexive(){
+        return getSourceAnchor().getRelatedWidget() == getTargetAnchor().getRelatedWidget();
+    }
+    
+    
+    @Override
+    protected Rectangle calculateClientArea() {              
+        Rectangle bounds = null;
+        if(this.getControlPoints().size()>0){           
+            for(Point p : this.getControlPoints()){
+              if(bounds==null)
+                  bounds = new Rectangle(p);
+              else
+                  bounds.add(p);
+            }
+            bounds.grow(5,5);         
+        }    
+        if(isReflexive()){
+            Widget related = this.getTargetAnchor().getRelatedWidget();
+            bounds = related.convertLocalToScene(related.getBounds());
+            bounds.grow(10, 10);
+        }
+        if(bounds==null)
+            bounds = super.calculateClientArea();
+           
+        return bounds;
+    }
+    
+ 
+    
+    //returns prefered location for an edge -1 for left and 1 for right
+    private int edgeBalance(Widget nodeWidget) {   
+        if(scene == null)
+            return 1;
+        
+        Point nodeLocation = nodeWidget.getLocation();
+        int left = 0, right = 0;
+
+        Object node = scene.findObject(nodeWidget);
+    
+        for(Object e : scene.findNodeEdges(node, true, true)) {//inputedges
+            ConnectionWidget cw = (ConnectionWidget) scene.findWidget(e);
+            
+            if(cw != this) {                
+                Widget targetNodeWidget = cw.getTargetAnchor().getRelatedWidget();
+
+                Point location;
+                if(targetNodeWidget == nodeWidget) {
+                    Widget sourceNodeWidget = cw.getSourceAnchor().getRelatedWidget();
+                    location = sourceNodeWidget.getLocation();
+                } else {
+                    location = targetNodeWidget.getLocation();
+                }
+
+                if(location.x < nodeLocation.x)
+                    left++;
+                else 
+                    right++;
+            }
+        }    
+        if(left < right)
+            return -1;
+        else
+            return 1;
+    } 
+    
+    
+    
+    
+    /**
+     * if the edge is reflexive its painted as a cyclic edge
+     * if there are 2 controlpoints the connection is painted as a straight line from the source to the targetanchor
+     * if there are more as 2 controlpoints the connection path between 2 control points is painted as bezier curve
+     */
+       
+    @Override
+    protected void paintWidget () {  
+
+        List<Point> contrPoints = this.getControlPoints();
+        int listSize = contrPoints.size();
+                
+        Graphics2D gr = getGraphics ();
+        
+        if (listSize <= 2) {
+            if(isReflexive()) { //special case for reflexive connection widgets    
+                Widget related = this.getTargetAnchor().getRelatedWidget();
+                int position = this.edgeBalance(related);
+                Rectangle bounds = related.convertLocalToScene(related.getBounds());
+                gr.setColor (getLineColor()); 
+                Point first = new Point();
+                Point last = new Point();
+                double centerX = bounds.getCenterX();
+                first.x = (int) (centerX + bounds.width / 4);          
+                first.y = bounds.y + bounds.height;
+                last.x = first.x;
+                last.y = bounds.y;
+
+                gr.setStroke(this.getStroke());
+
+                double cutDistance = this.getTargetAnchorShape().getCutDistance();
+                double anchorAngle = Math.PI/-3.0;
+                double cutX = Math.abs(Math.cos(anchorAngle)*cutDistance); 
+                double cutY = Math.abs(Math.sin(anchorAngle)*cutDistance);
+                int ydiff=first.y-last.y; 
+                int endy = -ydiff;
+                double height=bounds.getHeight();
+                double cy = height/4.0;
+                double cx=bounds.getWidth()/5.0;
+                double dcx = cx*2;
+                GeneralPath gp = new GeneralPath();
+                gp.moveTo(0, 0);
+                gp.quadTo(0, cy, cx, cy);
+                gp.quadTo(dcx, cy, dcx, -height/2.0);
+                gp.quadTo(dcx, endy - cy, cy, -(cy+ydiff));
+                gp.quadTo(cutX*1.5, endy - cy, cutX, endy-cutY);   
+
+                AffineTransform af = new AffineTransform();           
+                AnchorShape anchorShape = this.getTargetAnchorShape();           
+
+                if(position < 0) {
+                    first.x = (int) (centerX - bounds.width / 4);        
+                    af.translate(first.x, first.y);
+                    af.scale(-1.0, 1.0);
+                    last.x = first.x;
+                } else {
+                    af.translate(first.x, first.y);
+                }
+                Shape s = gp.createTransformedShape(af);  
+                gr.draw(s);
+
+                if (last != null) {
+                    AffineTransform previousTransform = gr.getTransform ();
+                    gr.translate (last.x, last.y);  
+
+                    if(position < 0)
+                        gr.rotate(Math.PI - anchorAngle);
+                    else                  
+                        gr.rotate (anchorAngle);
+
+                    anchorShape.paint (gr, false);
+                    gr.setTransform (previousTransform);
+                }                                      
+                   
+            } else {
+                super.paintWidget();
+            }
+            return;
+        }
+           
+        //bezier curve... 
+        GeneralPath curvePath = new GeneralPath();
+        Point lastControlPoint = null;
+        double lastControlPointRotation = 0.0;
+       
+        Point prev = null;                 
+        for (int i = 0; i < listSize - 1; i++) {
+            Point cur = contrPoints.get(i);
+            Point next = contrPoints.get(i + 1);
+            Point nextnext = null;
+            if (i < listSize - 2) {
+                nextnext = contrPoints.get(i + 2);
+            }     
+            
+            double len = cur.distance(next);                
+            double scale = len * BEZIER_SCALE;     
+            Point bezierFrom = null;//first ControlPoint         
+            Point bezierTo = null;//second ControlPoint
+            
+            if (prev == null) {
+                //first point 
+                curvePath.moveTo(cur.x, cur.y);//startpoint
+                bezierFrom = cur;              
+            } else {            
+                bezierFrom = new Point(next.x - prev.x, next.y - prev.y);
+                bezierFrom = scaleVector(bezierFrom, scale);
+                bezierFrom.translate(cur.x, cur.y); 
+            }
+       
+            if (nextnext == null) {//next== last point (curve to)               
+                lastControlPoint=next;  
+                bezierTo = next;//set 2nd intermediate point to endpoint              
+                GeneralPath lastseg = this.subdivide(cur, bezierFrom, bezierTo, next);
+                if(lastseg != null)
+                    curvePath.append(lastseg, true);
+                break;                
+            } else {
+                bezierTo = new Point(cur.x - nextnext.x, cur.y - nextnext.y);
+                bezierTo = scaleVector(bezierTo, scale);
+                bezierTo.translate(next.x, next.y); 
+            }
+          
+            curvePath.curveTo(
+                    bezierFrom.x, bezierFrom.y,//controlPoint1
+                    bezierTo.x, bezierTo.y,//controlPoint2
+                    next.x,next.y
+            );        
+            prev = cur;
+        }
+        Point2D cur = curvePath.getCurrentPoint();
+        Point next = lastControlPoint;
+        
+        lastControlPointRotation = //anchor anchorAngle 
+            Math.atan2 (cur.getY() - next.y, cur.getX() - next.x);
+                         
+        Color previousColor = gr.getColor();
+        gr.setColor (getLineColor());    
+        Stroke s = this.getStroke();
+        gr.setStroke(s);
+        gr.setColor(this.getLineColor());
+        gr.draw(curvePath);
+                      
+        AffineTransform previousTransform = gr.getTransform ();    
+        gr.translate (lastControlPoint.x, lastControlPoint.y);       
+        gr.rotate (lastControlPointRotation);
+        AnchorShape targetAnchorShape = this.getTargetAnchorShape();           
+        targetAnchorShape.paint (gr, false);
+        gr.setTransform (previousTransform);
+       
+        //paint ControlPoints if enabled
+        if (isPaintControlPoints()) {
+            int last = listSize - 1;
+            for (int index = 0; index <= last; index ++) {
+                Point point = contrPoints.get (index);
+                previousTransform = gr.getTransform ();
+                gr.translate (point.x, point.y);
+                if (index == 0  ||  index == last)
+                    getEndPointShape().paint (gr);
+                else
+                    getControlPointShape().paint (gr);
+                gr.setTransform (previousTransform);
+            }
+           
+        }
+        gr.setColor(previousColor);
+    }
+    
+    
+    
+    private GeneralPath subdivide (Point b0, Point b1, Point b2, Point b3) {            
+        double cutDistance = getTargetAnchorShape().getCutDistance();
+        double minDistance = cutDistance - ENDPOINT_DEVIATION;
+        /**
+         * if the cutDistance is valid the last segment of the curve
+         * gets reduced by subdivision until the distance of the endpoint(epDistance) 
+         * satisfys the condition (cutDistance > epDistance > (cutDistance - ENDPOINT-DEVIATION)
+         */
+        if(cutDistance > minDistance && minDistance > 0 ) {
+            GeneralPath path = new GeneralPath(); 
+            
+            path.moveTo(b0.x, b0.y);
+            
+            CubicCurve2D.Double left = new CubicCurve2D.Double(
+                    b0.x, b0.y, 
+                    b1.x, b1.y,
+                    b2.x, b2.y, 
+                    b3.x, b3.y);
+            
+            CubicCurve2D right=new CubicCurve2D.Double();
+            left.subdivide(left, right);   
+            double distance = b3.distance(left.getP2());
+            //if the distance is bigger as the cutDistance the left segment is added
+            //and the right segment is divided again
+            while(distance>cutDistance){                    
+                path.append(left, true);
+                right.subdivide(left, right);
+                distance = b3.distance(left.getP2());
+                //if the devision removed to much the left segment is divided
+                while(distance < minDistance) {                            
+                    //changes the distance to ~ (distance+distance/2)
+                    left.subdivide(left, right);
+                    distance = b3.distance(left.getP2());
+                }
+            }                  
+            //append the last segment with (minDistance < distance < cutDistance)
+            //actually we should check if the a division happend, but this is very unlikly
+            path.append(left, true);         
+            return path;
+        }
+        return null;
+    }
+    
+  
+   
+    
+       
+    private static Point scaleVector(Point vector, double len) {
+        double scale = Math.sqrt(vector.x * vector.x + vector.y * vector.y);
+        if(scale==0.0) return vector;
+        scale = len / scale;          
+        return new Point(
+                Math.round(vector.x * (float)scale), 
+                Math.round(vector.y * (float)scale));
+    }
+     
+}    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,360 @@
+package at.ssw.visualizer.cfg.visual;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.Line2D;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.api.visual.anchor.Anchor;
+import org.netbeans.api.visual.router.Router;
+import org.netbeans.api.visual.widget.ConnectionWidget;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ * Router Class with Collision Detection
+ * 
+ *
+ * The returned path is a straight line there is no node widget between the source and the target node,
+ * if there are nodewidgets in between it tries to find a path around those abstacles to avoid collisions.
+ * The algorithm for the search of this path is limited by a fixed number of iterations defined in 
+ * NUMER_OF_ITERATIONS to return a result in reasonable time. If the calculation exceeds this limit the 
+ * path returned contains at least 1 collision with a nodewidget.  
+ */
+
+public class PolylineRouter implements Router {
+    private static final float FACTOR = 0.70f;
+    
+    private static final int HEXPAND = 3;
+    private static final int VEXPAND = 3;
+    private static final int NUMBER_OF_ITERATIONS = 8;   
+    
+    WidgetCollisionCollector collector;
+    
+     
+    public PolylineRouter(WidgetCollisionCollector collector){
+        this.collector=collector;
+    }
+   
+  
+    public List<Point> routeConnection(final ConnectionWidget widget) {       
+        if(!widget.isVisible()) return Collections.<Point>emptyList();
+   
+        Anchor sourceAnchor = widget.getSourceAnchor();
+        Anchor targetAnchor = widget.getTargetAnchor();
+         
+        if(sourceAnchor == null || targetAnchor == null) 
+            return null;
+        
+        Point start = sourceAnchor.compute(widget.getSourceAnchorEntry()).getAnchorSceneLocation();
+        Point end =   targetAnchor.compute(widget.getTargetAnchorEntry()).getAnchorSceneLocation();
+        
+        Widget sourceWidget = sourceAnchor.getRelatedWidget();
+        Widget targetWidget = targetAnchor.getRelatedWidget();  
+        
+        
+        if(sourceWidget == targetWidget){//reflexive edges doesnt need any path      
+            return Collections.<Point>emptyList();
+        }
+           
+        List<Widget> nodeWidgets = new ArrayList<>();
+        
+        if(collector != null){
+            collector.collectCollisions(nodeWidgets);    
+            //source and target widget are not treatet as obstacle
+            nodeWidgets.remove(sourceWidget);
+            nodeWidgets.remove(targetWidget);
+        }
+                            
+        List<Point> controlPoints = optimize(nodeWidgets, widget, start, end); 
+              
+        //size==2 => straight line
+        //size==3 => ensures a collision between cp0 and cp2 therefore its not possible to simplify it
+        if(controlPoints.size() > 3)
+            controlPoints = simplify(nodeWidgets, controlPoints);
+        
+        return controlPoints;        
+    }   
+    
+    
+    private List<Point> simplify(Collection<Widget> nodeWidgets, List<Point> list) {        
+        List<Point> result = new ArrayList<>();
+        result.add( list.get(0) );//add startpoint
+        for (int i = 1; i < list.size(); i++) {
+            Point prev = list.get(i - 1);
+            for (int j = i; j < list.size(); j++) {
+                Point cur = list.get(j);
+                if (!intersects(nodeWidgets, prev, cur)) {
+                    i = j;
+                }               
+            }
+            result.add(list.get(i));
+        }      
+        return result;
+    }
+    
+    /**
+     * Computates the Anchorposition like the Rectangular anchor for a
+     * given widget as source/target and a controlpoint as opposit anchorposition
+     */
+     
+    private Point computateAnchorPosition(Widget relatedWidget, Point controlPoint) {
+        Rectangle bounds = relatedWidget.getBounds();
+        Point relatedLocation = relatedWidget.getLocation();//center of the widget
+       
+        if (bounds.isEmpty ()  || relatedLocation.equals (controlPoint))
+            return relatedLocation;
+
+        float dx = controlPoint.x - relatedLocation.x;
+        float dy = controlPoint.y - relatedLocation.y;
+
+        float ddx = Math.abs (dx) / (float) bounds.width;
+        float ddy = Math.abs (dy) / (float) bounds.height;
+
+        float scale = 0.5f / Math.max (ddx, ddy);
+
+        Point point = new Point (Math.round (relatedLocation.x + scale * dx), 
+                Math.round (relatedLocation.y + scale * dy));
+        return point;
+    }
+    
+   
+  
+    private List<Point> optimize(Collection<Widget> nodeWidgets, ConnectionWidget connWidget, Point start, Point end) {
+        
+        List<Point> list = new ArrayList<>();
+        list.add(start);
+        list.add(end);
+                           
+        boolean progress = true;
+        
+        for (int j = 0; progress && j < NUMBER_OF_ITERATIONS ; j++) {
+            progress = false;                  
+            List<Point> newList = new ArrayList<>();              
+            for (int i = 0; i < list.size() - 1 ; i++) {
+                Point cur = list.get(i);
+                Point next = list.get(i + 1);
+                newList.add(cur);
+                List<Point> intermediate = optimizeLine(nodeWidgets, cur, next);
+                if (intermediate != null && intermediate.size() > 0) { 
+                    progress = true;
+                    newList.addAll(intermediate);//insert new controlpoints between cur and next
+                } 
+            }            
+            newList.add(list.get(list.size()-1));//add endpoint of the polyline
+            list = newList;   
+            
+        }
+               
+        if(list.size() > 2) {          
+            Widget sourceNode = connWidget.getSourceAnchor().getRelatedWidget();
+            Widget targetNode = connWidget.getTargetAnchor().getRelatedWidget();
+            Rectangle sourceBounds = sourceNode.convertLocalToScene(sourceNode.getBounds());
+            Rectangle targetBounds = targetNode.convertLocalToScene(targetNode.getBounds());
+            sourceBounds.grow(HEXPAND, VEXPAND);
+            
+            /**
+             * add only points which are not intersecting the source and the target 
+             * widget bounds caused by invalid bad anchor positions. The first 
+             * and the last point is ignored cause the anchor is recalculated 
+             * anyway.
+             */
+            ArrayList<Point> tmp = new ArrayList<>();
+            int listSize=list.size();
+            tmp.add(list.get(0));
+            int i=0;
+            while(++i < listSize-1) {
+                Point p = list.get(i);
+                if(!sourceBounds.contains(p) || !targetBounds.contains(p))
+                    tmp.add(p);               
+            }
+           
+            tmp.add(list.get(i));
+            if(tmp.size() < 3)
+                return tmp;
+            
+            list=tmp;                    
+            //calculate a proper anchor position using the second/penultimate controlpoint for start/end
+            start = this.computateAnchorPosition(connWidget.getSourceAnchor().getRelatedWidget(), list.get(1));            
+            end = this.computateAnchorPosition(connWidget.getTargetAnchor().getRelatedWidget(), list.get(list.size()-2));            
+            list.set(0,start);           
+            list.set(list.size()-1, end);         
+        }          
+        return list;
+    }
+ 
+    
+    /**
+     *  trys to optimize a line from p1 to p2 to avoid collisions with node widgets
+     *  returns null if the line doesn`t intersect with any nodewidget
+     *  or a list with immediate points between p1 and p2 to avoid collisions
+     */
+    private List<Point> optimizeLine(Collection<Widget> nodeWidgets, Point p1, Point p2) {        
+        Line2D line = new Line2D.Double(p1, p2);
+                     
+        for(Widget w : nodeWidgets ) {            
+            if( w.isVisible() ) {                              
+                Rectangle r = w.convertLocalToScene(w.getBounds());             
+                r.grow(HEXPAND, VEXPAND);
+       
+                if (!line.intersects(r)) continue;
+                  
+                Point location = w.getLocation();                
+                int distx = (int) (r.width * FACTOR);
+                int disty = (int) (r.height * FACTOR);
+                
+                int minIntersects = Integer.MAX_VALUE;
+                int min = Integer.MAX_VALUE;
+                List<Point> minSol = null;
+                for (int i = -1; i <= 1; i++) {
+                    for (int j = -1; j <= 1; j++) {
+                        if (i != 0 || j != 0) {                           
+                            Point cur = new Point(location.x + i * distx, location.y + j * disty);
+                            List<Point> list1 = new ArrayList<>();
+                            list1.add(p1);
+                            list1.add(cur);
+                            list1.add(p2);                                                 
+                            int crossProd = Math.abs(crossProduct(p1, cur, p2));
+                            if (!intersects(w, list1)) {
+                                Line2D line1 = new Line2D.Float(p1, cur);
+                                Line2D line2 = new Line2D.Float(p2, cur);
+                                int curIntersects = this.countNodeIntersections(nodeWidgets, line1, line2);
+                                
+                                if (curIntersects < minIntersects
+                                        || (curIntersects == minIntersects && crossProd < min)) {
+                                    minIntersects = curIntersects;
+                                    min = crossProd;
+                                    minSol = new ArrayList<>();
+                                    minSol.add(cur);
+                                }
+                            }
+
+                            if (i == 0 || j == 0) {
+                                Point cur1, cur2;
+                                if (i == 0) {
+                                      cur1 = new Point(location.x + distx/2, location.y + j * disty);
+                                      cur2 = new Point(location.x - distx/2, location.y + j * disty);
+                                } else { // (j == 0) 
+                                    cur1 = new Point(location.x + i * distx, location.y + disty/2);
+                                    cur2 = new Point(location.x + i * distx, location.y - disty/2);
+                                }
+
+                                Point vec1 = new Point(p1.x - cur1.x, p1.y - cur1.y);
+                                int offset1 = vec1.x * vec1.x + vec1.y * vec1.y;
+
+                                Point vec2 = new Point(p1.x - cur2.x, p1.y - cur2.y);
+                                int offset2 = vec2.x * vec2.x + vec2.y * vec2.y;
+
+                                if (offset2 < offset1) {
+                                    Point tmp = cur1;
+                                    cur1 = cur2;
+                                    cur2 = tmp;
+                                }
+
+                                List<Point> list2 = new ArrayList<>();
+                                list2.add(p1);
+                                list2.add(cur1);
+                                list2.add(cur2);
+                                list2.add(p2);
+
+                                int cross1 = crossProduct(p1, cur1, cur2);
+                                int cross2 = crossProduct(cur1, cur2, p2);
+
+                                if (cross1 > 0) {
+                                    cross1 = 1;
+                                } else if (cross1 < 0) {
+                                    cross1 = -1;
+                                }
+                                
+                                if (cross2 > 0) {
+                                    cross2 = 1;
+                                } else if (cross2 < 0) {
+                                    cross2 = -1;
+                                }
+                                if ((cross1 == cross2 || cross1 == 0 || cross2 == 0) && !intersects(w, list2)) {                                 
+                                    Line2D line1 = new Line2D.Float(p1, cur1);
+                                    Line2D line2 = new Line2D.Float(cur1, cur2);
+                                    Line2D line3 = new Line2D.Float(p2, cur2);
+                                    int curIntersects = this.countNodeIntersections(nodeWidgets, line1, line2, line3);
+                                   
+                                    // This is a bit better
+                                    crossProd--;
+
+                                    if (curIntersects < minIntersects
+                                            || (curIntersects == minIntersects && crossProd < min)) {
+                                        minIntersects = curIntersects;
+                                        min = crossProd;
+                                        minSol = new ArrayList<>();
+                                        minSol.add(cur1);
+                                        minSol.add(cur2);                                       
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }           
+                if (minSol != null) {      
+                    return minSol;
+                } 
+            }
+        }
+        return null;
+    }
+    
+    
+   
+    private int countNodeIntersections(Collection<Widget> nodeWidgets, Line2D... lines){
+        int count=0;     
+        for(Widget nw : nodeWidgets){
+            if(nw.isVisible()) {
+                Rectangle bounds = nw.convertLocalToScene(nw.getBounds());
+                for( Line2D line : lines){
+                    if(line.intersects(bounds))
+                        count++;
+                }
+            }
+        }
+        return count;
+    }
+    
+    
+    private boolean intersects(Collection<Widget> nodeWidgets, Point start, Point end) {
+        List<Point> pointlist = new ArrayList<>();
+        pointlist.add(start);
+        pointlist.add(end);
+
+        for(Widget w : nodeWidgets){
+            if(w.isVisible() && intersects(w, pointlist)) {
+                return true;
+            }
+        }
+        return false;
+    }
+        
+    
+    private boolean intersects(Widget w, List<Point> list) {
+        Rectangle r = w.convertLocalToScene(w.getBounds());
+        r.grow(HEXPAND, VEXPAND);
+        return intersects(list, r);
+    }
+    
+    
+    private boolean intersects(List<Point> list, Rectangle rect){
+        for(int i=1; i < list.size(); i++) {
+            Point cur = list.get(i-1);
+            Point next = list.get(i);   
+            if(rect.intersectsLine(cur.x, cur.y, next.x, next.y))
+                return true;
+        }
+        return false;
+    }
+
+    
+    private int crossProduct(Point p1, Point p2, Point p3) {
+        Point off1 = new Point(p1.x - p2.x, p1.y - p2.y);
+        Point off2 = new Point(p3.x - p2.x, p3.y - p2.y);
+        return (off1.x * off2.y - off1.y * off2.x);
+    }
+        
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouterV2.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,393 @@
+package at.ssw.visualizer.cfg.visual;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.Line2D;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.api.visual.anchor.Anchor;
+import org.netbeans.api.visual.router.Router;
+import org.netbeans.api.visual.widget.ConnectionWidget;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ * Router Class with Collision Detection
+ * 
+ *
+ * The returned path is a straight line there is no node widget between the source and the target node,
+ * if there are nodewidgets in between it tries to find a path around those abstacles to avoid collisions.
+ * The algorithm for the search of this path is limited by a fixed number of iterations defined in 
+ * NUMER_OF_ITERATIONS to return a result in reasonable time. If the calculation exceeds this limit the 
+ * path returned contains at least 1 collision with a nodewidget. 
+ * 
+ * This class intend to solve the same problem as the class PolyLineRouter but
+ * uses slightly different methods.
+ * + uses another algorithm for solving the collision.
+ * + the obstacle bounds are calulated in advance to avoid a recalculation.
+ * - there is no heuristic, the shortest path around the widget is choosen asap.
+ * 
+ * 
+ *  
+ */
+
+public class PolylineRouterV2 implements Router {    
+    private static final int HEXPAND = 3;
+    private static final int VEXPAND = 3;
+    private static final int NUMBER_OF_ITERATIONS = 8;   
+    
+    WidgetCollisionCollector collector;
+    
+     
+    public PolylineRouterV2(WidgetCollisionCollector collector){
+        this.collector=collector;
+    }
+   
+   
+    public List<Point> routeConnection(final ConnectionWidget widget) {       
+        if(!widget.isVisible()) return Collections.<Point>emptyList();
+   
+        Anchor sourceAnchor = widget.getSourceAnchor();
+        Anchor targetAnchor = widget.getTargetAnchor();
+         
+        if(sourceAnchor == null || targetAnchor == null) 
+            return null;
+        
+        Point start = sourceAnchor.compute(widget.getSourceAnchorEntry()).getAnchorSceneLocation();
+        Point end =   targetAnchor.compute(widget.getTargetAnchorEntry()).getAnchorSceneLocation();
+
+        Widget sourceWidget = sourceAnchor.getRelatedWidget();
+        Widget targetWidget = targetAnchor.getRelatedWidget(); 
+        
+               
+        if(sourceWidget == targetWidget){//reflexive edges doesnt need any path      
+            return Collections.<Point>emptyList();
+        }
+        
+        
+        Point srcCenter = this.getSceneLocation(sourceWidget);
+        Point tarCenter = this.getSceneLocation(targetWidget);
+        
+        List<Widget> widgetObstacles = new ArrayList<>();
+        
+        if(collector != null){
+            collector.collectCollisions(widgetObstacles);                    
+        }
+        
+        List<Rectangle> obstacles = new ArrayList<>(widgetObstacles.size());
+        this.collectObstacles(obstacles, widgetObstacles, widget);
+       
+                    
+        List<Point> controlPoints = optimize(obstacles, srcCenter, tarCenter);     
+//        size==2 => straight line
+//        size==3 => ensures a collision between cp0 and cp2 therefore its not possible to simplify it
+        if(controlPoints.size() > 3){
+            Point rstart = this.computateAnchorPosition(sourceWidget, controlPoints.get(1));            
+            Point rend  = this.computateAnchorPosition(targetWidget, controlPoints.get(controlPoints.size()-2)); 
+            controlPoints.set(0, rstart);           
+            controlPoints.set(controlPoints.size()-1, rend);       
+            controlPoints = simplify(obstacles, controlPoints);
+        } else if (controlPoints.size()>=2){
+                //use old points
+            controlPoints.set(0, start);           
+            controlPoints.set(controlPoints.size()-1, end);           
+        
+        }
+        return controlPoints;        
+    }  
+    
+    
+    private int collectObstacles(List<Rectangle> colrects, List<Widget> colwidgets , ConnectionWidget cw){        
+        int count=0;                        
+        Anchor sourceAnchor = cw.getSourceAnchor();
+        Anchor targetAnchor = cw.getTargetAnchor();
+        Widget sourceWidget = sourceAnchor.getRelatedWidget();
+        Widget targetWidget = targetAnchor.getRelatedWidget(); 
+        Point start = sourceAnchor.compute(cw.getSourceAnchorEntry()).getAnchorSceneLocation();
+        Point end =   targetAnchor.compute(cw.getTargetAnchorEntry()).getAnchorSceneLocation();
+                        
+        for(Widget w : colwidgets){
+            
+            if(w==sourceWidget || w == targetWidget) continue;
+           
+            Rectangle r = w.convertLocalToScene(w.getBounds());
+            r.grow(HEXPAND, VEXPAND);
+            if(r.intersectsLine(start.x,start.y,end.x,end.y))
+                count++;
+            colrects.add(r);
+        }
+        return count;
+    }
+    
+    
+    private Point center (Rectangle bounds) {
+        return new Point (bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
+    }
+
+    /**
+     * Returns the scene location of a related widget.
+     * bounds might be null if the widget was not added to the scene
+     * @return the scene location; null if no related widget is assigned
+     */
+    public Point getSceneLocation (Widget relatedWidget) {
+        if (relatedWidget != null) {
+            Rectangle bounds = relatedWidget.getBounds ();
+            if(bounds != null)
+                return center(relatedWidget.convertLocalToScene(bounds));           
+        }
+        return null;
+    }
+       
+    /**
+     * Computates the Anchorposition like the Rectangular anchor for a
+     * given widget as source/target and a controlpoint as opposit anchorposition
+     */
+     
+    private Point computateAnchorPosition(Widget relatedWidget, Point controlPoint) {
+        Rectangle bounds = relatedWidget.getBounds();
+        
+        //todo: fix, center of widget must be cacluated trough the bounds 
+        //since there are some wheird widgets where the location is not the center of the widget
+        Point relatedLocation = relatedWidget.getLocation();//center of the widget
+       
+        if (bounds.isEmpty ()  || relatedLocation.equals (controlPoint))
+            return relatedLocation;
+
+        float dx = controlPoint.x - relatedLocation.x;
+        float dy = controlPoint.y - relatedLocation.y;
+
+        float ddx = Math.abs (dx) / (float) bounds.width;
+        float ddy = Math.abs (dy) / (float) bounds.height;
+
+        float scale = 0.5f / Math.max (ddx, ddy);
+
+        Point point = new Point (Math.round (relatedLocation.x + scale * dx), 
+                Math.round (relatedLocation.y + scale * dy));
+        return point;
+    }
+    
+    private List<Point> simplify(List<Rectangle> obstacles, List<Point> list) {        
+        List<Point> result = new ArrayList<>(list.size());
+        result.add( list.get(0) );//add startpoint
+        for (int i = 1; i < list.size(); i++) {
+            Point prev = list.get(i - 1);
+            for (int j = i; j < list.size(); j++) {
+                Point cur = list.get(j);
+                if (!intersects(obstacles, prev, cur)) {
+                    i = j;
+                }               
+            }
+            result.add(list.get(i));
+        }      
+        return result;
+    }
+  
+    private List<Point> optimize(List<Rectangle> nodeWidgets, Point start, Point end) {
+        
+        List<Point> list = new ArrayList<>();
+        list.add(start);
+        list.add(end);
+                           
+        boolean progress = true;
+        
+        for (int j = 0; progress && j < NUMBER_OF_ITERATIONS ; j++) {
+            progress = false;                  
+            List<Point> newList = new ArrayList<>();      
+            for (int i = 0; i < list.size() - 1 ; i++) {
+                Point cur = list.get(i);
+                Point next = list.get(i + 1);
+                newList.add(cur);               
+                List<Point> intermediate = optimizeLine(nodeWidgets, cur, next);
+                if (intermediate != null && intermediate.size() > 0) { 
+                    progress = true;                  
+                    newList.addAll(intermediate);//insert new controlpoints between cur and next
+                } 
+            }           
+            newList.add(list.get(list.size()-1));//add endpoint of the polyline
+            list = newList;   
+            
+        }
+        
+        return list;
+    }
+ 
+  
+    /**
+     *  trys to optimize a line from p1 to p2 to avoid collisions with rectangles
+     *  returns null if the line doesn`t intersect with any nodewidget or
+     *  if the obstacles are overlapping
+     *  ----------------------------------------------------------------------
+     *  if the collision is solved it returns a list with immediate points 
+     *  between p1 and p2. The points are taken from hull points of and grown 
+     *  rectangle.
+     */
+    private List<Point> optimizeLine(List<Rectangle> obstacles, Point p1, Point p2) {        
+        Line2D line = new Line2D.Double(p1, p2);
+        boolean inbounds=false;
+        Rectangle ibr=null;
+        ArrayList<Point> sol = new ArrayList<>();
+        boolean leftIntersection;
+        boolean rightIntersection; 
+        boolean bottomIntersection; 
+        boolean topIntersection; 
+        Point interLeft=new Point();
+        Point interRight=new Point();
+        Point interBot=new Point();
+        Point interTop=new Point();
+        
+    
+        
+        for(Rectangle r : obstacles ) {                      
+            if (!line.intersects(r)) continue;
+            
+            int w=r.width+2;
+            int h=r.height+2;
+            Point topLeft = r.getLocation();
+            topLeft.x-=1;
+            topLeft.y-=1;
+            Point topRight = new Point(topLeft.x+w, topLeft.y);
+            Point bottomLeft = new Point(topLeft.x, topLeft.y+h);
+            Point bottomRight = new Point(topRight.x, bottomLeft.y);  
+            leftIntersection = findIntersectionPoint(p1, p2, topLeft, bottomLeft, interLeft);
+            rightIntersection = findIntersectionPoint(p1, p2, topRight, bottomRight, interRight);
+            bottomIntersection = findIntersectionPoint(p1, p2, bottomLeft, bottomRight, interBot);
+            topIntersection = findIntersectionPoint(p1, p2, topLeft, topRight, interTop);
+            
+            //Intersection points are not used yet. This could be actually a 
+            //good approach to avoid additional collisions because it would be
+            //still the same vector.
+
+            if(leftIntersection) {                      
+                if(topIntersection) {//left and top   
+                    sol.add(topLeft);                       
+                }                        
+                else if(bottomIntersection){//left and bottom
+                    sol.add(bottomLeft);                                   
+                }
+                else if(rightIntersection){//left and right
+                    double disttl = topLeft.distance(p1);
+                    double distbl = bottomLeft.distance(p1);
+                    if(disttl > distbl){
+                        //pass at the bottom
+                        double distbr = bottomRight.distance(p1);
+                        if(distbl < distbr){
+                            //from the left to the right
+                            sol.add(bottomLeft);
+                            sol.add(bottomRight);
+                        } else {
+                            //from the right to the left
+                            sol.add(bottomRight);
+                            sol.add(bottomLeft);
+                        }
+                    } else {
+                        //pass at the top
+                        double disttr = topRight.distance(p1);
+                        if(disttl < disttr){
+                            //from the left to the right
+                            sol.add(topLeft);
+                            sol.add(topRight);
+                        } else {
+                            //from the right to the left
+                            sol.add(topRight);
+                            sol.add(topLeft);
+                        }
+                    }                        
+                 } else {//only left => inside bounds 
+                    inbounds=true;                                  
+                 } 
+            } else if (rightIntersection) {                
+                if(topIntersection) {//right and top
+                    sol.add(topRight);
+                }
+                else if(bottomIntersection){//right and bottom
+                    sol.add(bottomRight);
+                } else { //only right => inside the bounds
+                    inbounds=true;                             
+                }                  
+            } else if (topIntersection && bottomIntersection) {//top and bottom
+                double disttop = interTop.distance(p1);
+                double distbot = interBot.distance(p1);
+                if(disttop < distbot ){
+                    //from the top to the bottom
+                    double distleft = interTop.distance(topLeft);
+                    double distright = interTop.distance(topRight);
+                    if(distleft < distright){
+                        //pass left
+                        sol.add(topLeft);
+                        sol.add(bottomLeft);
+                    } else {
+                        //pass right
+                        sol.add(topRight);
+                        sol.add(bottomRight);
+                    }   
+                } else {
+                    //from the bottom to the top
+                    double distleft = interBot.distance(bottomLeft);
+                    double distright = interBot.distance(bottomRight);
+                    if(distleft < distright){
+                        //pass left
+                        sol.add(bottomLeft);
+                        sol.add(topLeft);
+                    } else {
+                        //pass right
+                        sol.add(bottomRight);
+                        sol.add(topRight);
+                    }   
+                } 
+            } else {//only bottom or only top
+                inbounds=true;                 
+            } /* ENDIF */
+            
+            //breakpoint <-- collision detected
+            
+            if(sol.size()>0) {//solution found
+                assert(!inbounds);
+                return sol;
+            } else { //no solution found=> inbounds
+                assert(inbounds);
+                assert(sol.size()==0);
+                //handle collision or just skip it and search for the next collisionj               
+                ibr=r;
+                //jump out of the loop to able to interate over the obstacles
+                break;
+            } 
+        }/* end foreach obstacle */
+        
+        if(inbounds || ibr != null){
+            assert(inbounds);
+            assert(ibr!=null);        
+        }       
+        return null;//no collison found
+    }/* end optimizeLine */
+    
+ 
+  
+    //check intersection between line p0->p1 for a given set of obstacles
+    private static boolean intersects(List<Rectangle> obstacles, Point p0, Point p1) {
+        for(Rectangle r : obstacles){
+            if(r.intersectsLine(p0.x, p0.y, p1.x, p1.y))
+                return true;         
+        }
+        return false;
+    }
+    
+   
+    private boolean findIntersectionPoint(
+            Point p0, Point p1, Point p2, Point p3, Point pI) {
+        float q = (p0.y - p2.y)*(p3.x - p2.x) - (p0.x - p2.x)*(p3.y - p2.y);
+        float d = (p1.x - p0.x)*(p3.y - p2.y) - (p1.y - p0.y)*(p3.x - p2.x);
+        
+        //parallel ?
+        if(d==0) return false;
+          
+        float r = q / d;
+        q = (p0.y - p2.y)*(p1.x - p0.x) - (p0.x - p2.x)*(p1.y - p0.y);
+        
+        float s = q / d;
+        if(r<0 || r>1 || s<0 || s>1) return false;
+        
+        pI.x = p0.x + (int) (0.5f + r * (p1.x - p0.x));
+        pI.y = p0.y + (int) (0.5f + r * (p1.y - p0.y));
+        return true;
+    }    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/SplineConnectionWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,541 @@
+package at.ssw.visualizer.cfg.visual;
+
+import org.netbeans.api.visual.widget.ConnectionWidget;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.List;
+import org.netbeans.api.visual.anchor.AnchorShape;
+import org.netbeans.api.visual.graph.GraphScene;
+import org.netbeans.api.visual.widget.Scene;
+import org.netbeans.api.visual.widget.Widget;
+
+
+/**
+ *  In comparison to the default ConnectionWidget this class is able to connect 
+ *  widgets with a curve instead of a straight line sequence. 
+ *  In conjunction with a suitable router the connection will be a straight line 
+ *  or a curve depending on the amount and the position of the controlpoints. 
+ *  Controlpoints supplied by the router, are treated as curve intersection points.
+ *  For Reflexive edges the router doesn`t necessarily need to supply 
+ *  any controlpoints, they get painted by this automatically, this can be 
+ *  excepted if the router supplys more as 2 control points for a self edge,
+ *  then the edge gets painted with the default curve interpolation algorithm.
+ *  The method used for drawing curves uses a piecewise cubic interpolation 
+ *  algorithm. Between two control points a curve is painted as cubic bezier 
+ *  curve the, inner bezier points are calculated automatically with FMILL 
+ *  tangents and a chord parametrization, this interpolant is also known as
+ *  cutmull-rom spline. The resulting spline fullfills c^1 continuity.
+ *  The the end points the interpolation algorithm uses the bessel end condition.
+ */
+
+public class SplineConnectionWidget extends ConnectionWidget {     
+   private static final double ENDPOINT_DEVIATION = 3;//curve endpoint approximation accuracy
+   private static final double HIT_DISTANCE_SQUARE = 4.0;//distance for intersection test
+    private GraphScene scene=null;
+    private Point2D [] bezierPoints = null;
+ 
+    public SplineConnectionWidget(Scene scene) {
+        super(scene);   
+        if(scene instanceof GraphScene)
+            this.scene=(GraphScene) scene;
+    }
+    
+    //check for self - edge
+    private boolean isReflexive(){
+        return getSourceAnchor().getRelatedWidget() == getTargetAnchor().getRelatedWidget();
+    }
+    
+    
+    @Override
+    protected Rectangle calculateClientArea() {              
+        
+        Rectangle bounds = null;
+
+        if(this.getControlPoints().size()>2){
+            bezierPoints = createBezierPoints(getControlPoints());
+        }
+        //minmax method - returns the smallest bounding rectangle  
+        //Curves and surfaces for CAGD (3rd ed.), p.54  
+        //exact calculation of the bounding min rect
+        if(bezierPoints != null) {
+            Rectangle2D bounds2D = null;
+            for (int i = 0; i < bezierPoints.length; i++) {
+                Point2D point = bezierPoints[i];
+                if(bounds2D==null)
+                    bounds2D = new Rectangle2D.Double(point.getX(),point.getY(),0,0);
+                else
+                    bounds2D.add(point);
+            }
+            bounds = bounds2D.getBounds();
+            bounds.grow(2, 2);
+            
+        } else if (getControlPoints().size()>0){
+            for(Point p : this.getControlPoints()){
+              if(bounds==null)
+                  bounds = new Rectangle(p);
+              else
+                  bounds.add(p);
+            }
+            bounds.grow(5,5);     
+            
+        } else if (isReflexive()) {
+            Widget related = this.getTargetAnchor().getRelatedWidget();
+            bounds = related.convertLocalToScene(related.getBounds());
+            bounds.grow(10, 10);
+        }
+        
+        if(bounds==null)
+            bounds = super.calculateClientArea();
+
+        return bounds;
+    }
+ 
+    
+    /**
+     * if the edge is reflexive its painted as a cyclic self edge, if there 
+     * are two controlpoints the connection is painted as a straight line from 
+     * the source to the targetanchor, if there are more as 2 controlpoints the 
+     * connection path between two control points is painted as cutmull rom 
+     * spline with bessel end tangents.
+     */
+    @Override
+    protected void paintWidget () {       
+        List<Point> contrPoints = this.getControlPoints();
+        int listSize = contrPoints.size();
+  
+        Graphics2D gr = getGraphics ();
+        
+        if (listSize <= 2) {
+            this.bezierPoints=null;//set bezier Points null for calulateClientArea()
+            if(isReflexive()) { //special case for reflexive connection widgets    
+                this.drawReflexive(gr);
+            } else {
+                super.paintWidget();
+            }         
+            return;
+        }
+      
+        //bezier curve... listSize > 2
+        GeneralPath curvePath = new GeneralPath();      
+        double lastControlPointRotation = 0.0;
+        
+        
+        Point2D [] bezPoints  = this.createBezierPoints(contrPoints);
+        curvePath.moveTo(bezPoints[0].getX(), bezPoints[0].getY());//b00
+        
+        //last segment is added by subdivision thats why its -5
+        for (int i = 1; i < bezPoints.length-5; i+=3) {          
+            curvePath.curveTo(
+                    bezPoints[i].getX(), bezPoints[i].getY(),//b1i
+                    bezPoints[i+1].getX(), bezPoints[i+1].getY(),//b2i
+                    bezPoints[i+2].getX(), bezPoints[i+2].getY());//b3i   
+           
+        }        
+   
+        GeneralPath lastseg = subdivide2D(
+                bezPoints[bezPoints.length-4], 
+                bezPoints[bezPoints.length-3],
+                bezPoints[bezPoints.length-2],
+                bezPoints[bezPoints.length-1]);
+        
+
+        if(lastseg != null)
+            curvePath.append(lastseg, true);
+                    
+        Point2D cur = curvePath.getCurrentPoint();
+        Point lastControlPoint = contrPoints.get(listSize-1);
+        
+        lastControlPointRotation = //anchor anchorAngle 
+            Math.atan2 (cur.getY() - lastControlPoint.y, cur.getX() - lastControlPoint.x);
+  
+        gr.setStroke(getStroke());
+        gr.setColor(getLineColor());
+        gr.draw(curvePath);
+   
+                      
+        AffineTransform previousTransform = gr.getTransform ();    
+        gr.translate (lastControlPoint.x, lastControlPoint.y);       
+        gr.rotate (lastControlPointRotation);
+        AnchorShape targetAnchorShape = this.getTargetAnchorShape();           
+        targetAnchorShape.paint (gr, false);
+        gr.setTransform (previousTransform);
+       
+        //paint ControlPoints if enabled
+        if (isPaintControlPoints()) {
+            int last = listSize - 1;
+            for (int index = 0; index <= last; index ++) {
+                Point point = contrPoints.get (index);
+                previousTransform = gr.getTransform ();
+                gr.translate (point.x, point.y);
+                if (index == 0  ||  index == last)
+                    getEndPointShape().paint (gr);
+                else
+                    getControlPointShape().paint (gr);
+                gr.setTransform (previousTransform);
+            }
+           
+        }   
+    }
+    
+    private void drawReflexive(Graphics2D gr){
+        Widget related = this.getTargetAnchor().getRelatedWidget();
+        int position = this.edgeBalance(related);
+        Rectangle bounds = related.convertLocalToScene(related.getBounds());
+        gr.setColor (getLineColor()); 
+        Point first = new Point();
+        Point last = new Point();
+        double centerX = bounds.getCenterX();
+        first.x = (int) (centerX + bounds.width / 4);          
+        first.y = bounds.y + bounds.height;
+        last.x = first.x;
+        last.y = bounds.y;
+
+        gr.setStroke(this.getStroke());
+
+        double cutDistance = this.getTargetAnchorShape().getCutDistance();
+        double anchorAngle = Math.PI/-3.0;
+        double cutX = Math.abs(Math.cos(anchorAngle)*cutDistance); 
+        double cutY = Math.abs(Math.sin(anchorAngle)*cutDistance);
+        int ydiff=first.y-last.y; 
+        int endy = -ydiff;
+        double height=bounds.getHeight();
+        double cy = height/4.0;
+        double cx=bounds.getWidth()/5.0;
+        double dcx = cx*2;
+        GeneralPath gp = new GeneralPath();
+        gp.moveTo(0, 0);
+        gp.quadTo(0, cy, cx, cy);
+        gp.quadTo(dcx, cy, dcx, -height/2.0);
+        gp.quadTo(dcx, endy - cy, cy, -(cy+ydiff));
+        gp.quadTo(cutX*1.5, endy - cy, cutX, endy-cutY);   
+
+        AffineTransform af = new AffineTransform();           
+        AnchorShape anchorShape = this.getTargetAnchorShape();           
+
+        if(position < 0) {
+            first.x = (int) (centerX - bounds.width / 4);        
+            af.translate(first.x, first.y);
+            af.scale(-1.0, 1.0);
+            last.x = first.x;
+        } else {
+            af.translate(first.x, first.y);
+        }
+        Shape s = gp.createTransformedShape(af);  
+        gr.draw(s);
+
+        if (last != null) {
+            AffineTransform previousTransform = gr.getTransform ();
+            gr.translate (last.x, last.y);  
+
+            if(position < 0)
+                gr.rotate(Math.PI - anchorAngle);
+            else                  
+                gr.rotate (anchorAngle);
+
+            anchorShape.paint (gr, false);
+            gr.setTransform (previousTransform);
+        }                                      
+    }
+     
+    //returns prefered location for an edge -1 for left and 1 for right
+    private int edgeBalance(Widget nodeWidget) {   
+        if(scene == null)
+            return 1;
+        
+        Point nodeLocation = nodeWidget.getLocation();
+        int left = 0, right = 0;
+
+        Object node = scene.findObject(nodeWidget);
+    
+        for(Object e : scene.findNodeEdges(node, true, true)) {//inputedges
+            ConnectionWidget cw = (ConnectionWidget) scene.findWidget(e);
+            
+            if(cw != this) {                
+                Widget targetNodeWidget = cw.getTargetAnchor().getRelatedWidget();
+
+                Point location;
+                if(targetNodeWidget == nodeWidget) {
+                    Widget sourceNodeWidget = cw.getSourceAnchor().getRelatedWidget();
+                    location = sourceNodeWidget.getLocation();
+                } else {
+                    location = targetNodeWidget.getLocation();
+                }
+
+                if(location.x < nodeLocation.x)
+                    left++;
+                else 
+                    right++;
+            }
+        }    
+        if(left < right)
+            return -1;
+        else
+            return 1;
+    } 
+    
+    
+     private Point2D[] createBezierPoints(List<Point> list){
+        if(list.size()<3) return null ;
+        
+        
+        int lastIdx = list.size()-1;
+        
+
+        //chord length parametrization
+        double[] uis = new double[list.size()];
+        uis[0]=0;
+        uis[1] = list.get(1).distance(list.get(0));
+        for (int i = 1; i < uis.length; i++) {
+            Point cur = list.get(i);
+            Point prev = list.get(i-1);     
+            uis[i]=uis[i-1]+ cur.distance(prev);          
+        }
+          
+            
+        for (int i = 1; i < uis.length; i++) {
+            uis[i] /= uis[lastIdx];
+            
+        }
+        double[] delta = new double[uis.length-1];     
+        for (int i = 0; i < delta.length; i++) {
+            double ui = uis[i];
+            double uin = uis[i+1];
+            delta[i] = uin-ui;
+        }
+       
+        
+        //FMILL tangent directions (chord length) 
+        Point2D[] tangents  = new Point2D[list.size()];
+ 
+        for (int i = 1; i < list.size()-1; i++) {
+            Point xBefore = list.get(i-1);
+            Point xAfter = list.get(i+1);
+            Point2D.Double tangent = new Point2D.Double (xAfter.x - xBefore.x, xAfter.y - xBefore.y);          
+            tangents[i] = tangent;
+        }
+        
+        
+        Point2D [] bezPoints = new Point2D[(list.size()-1)*2+list.size()];
+        //Catmull-Rom
+        for (int i = 1; i < list.size()-1; i++) {                
+            Point b3i = list.get(i);
+            Point2D b3ib = b3iBefore(b3i, delta[i-1], delta[i], tangents[i]);
+            Point2D b3ia = b3iAfter(b3i, delta[i-1], delta[i], tangents[i]);
+            bezPoints[3*i] = b3i;
+            bezPoints[3*i-1] = b3ib;
+            bezPoints[3*i+1] = b3ia;
+        }             
+        bezPoints[0] = list.get(0);
+        bezPoints[bezPoints.length-1] = list.get(list.size()-1);
+
+        Point p0 = list.get(0);
+        Point p1 = list.get(1);
+        Point p2 = list.get(2);
+        Point pL_2 = list.get(lastIdx-2);
+        Point pL_1 = list.get(lastIdx-1);
+        Point pL = list.get(lastIdx);
+       
+        Point2D m1 = besselTangent(delta[0], delta[1], p0, p1, p2);
+        Point2D m0 = besselEndTangent(p0, p1, delta[0], m1);
+        
+        Point2D mLb = besselTangent(delta[delta.length-2], delta[delta.length-1],
+                pL_2,pL_1, pL);
+        Point2D mL = besselEndTangent(pL_1, pL, delta[delta.length-1], mLb);
+        
+        Point2D scaleM0 = scale(normalize(m0), p0.distance(p1));//increase distx/distxl to make curve rounder at the end
+        Point2D scaleML = scale(normalize(mL), pL.distance(pL_1));
+         //Catmull-Rom for bessel points 
+        Point2D b30a = b3iAfter(p0, delta[0], delta[0],scaleM0);
+        Point2D b33b = b3iBefore(pL, delta[delta.length-1], delta[delta.length-1],scaleML);
+         
+        bezPoints[1] = b30a;
+        bezPoints[bezPoints.length-2] = b33b;
+
+        return bezPoints;
+    }
+    
+     
+
+    private static Point2D besselTangent(double delta_ib, double delta_i, Point2D p0, Point2D p1 , Point2D p2){
+        double alpha_i = delta_ib/(delta_ib+delta_i);
+        
+        double x = (1-alpha_i)/delta_ib * (p1.getX() - p0.getX())
+                + alpha_i/delta_i * (p2.getX()-p1.getX());
+        double y = (1-alpha_i)/delta_ib * (p1.getY() - p0.getY())
+                + alpha_i/delta_i * (p2.getY()-p1.getY());
+       
+        return new Point2D.Double(x,y);
+    }
+    
+    private static Point2D besselEndTangent(Point2D p0, Point2D p1, double delta_u, Point2D m){
+        double x = 2*((p1.getX()-p0.getX())/delta_u) - m.getX();
+        double y = 2*((p1.getY()-p0.getY())/delta_u) - m.getY();
+        return new Point2D.Double(x,y);
+    }
+    
+    private static Point2D b3iBefore(Point2D b3i, double delta_ib, double delta_i, Point2D li){    
+        double x = b3i.getX() - (delta_ib/(3*(delta_ib+delta_i)))*li.getX();
+        double y = b3i.getY() - (delta_ib/(3*(delta_ib+delta_i)))*li.getY();   
+        return new Point.Double(x,y);      
+    }
+    
+    private static Point2D b3iAfter(Point2D b3i, double delta_ib,double delta_i,Point2D li){
+        double x = b3i.getX() + (delta_i/(3*(delta_ib+delta_i)))*li.getX();
+        double y = b3i.getY() + (delta_i/(3*(delta_ib+delta_i)))*li.getY();
+        return new Point.Double(x,y);      
+    }
+    
+    
+    
+    
+    //returns length of vector v
+    private static double norm(Point2D v){
+        return Math.sqrt(v.getX()*v.getX()+v.getY()*v.getY());
+    }
+     
+    //returns unity vector of vector v
+    private static Point2D normalize(Point2D v){
+        double norm = norm(v);
+        if(norm==0) return new Point2D.Double(v.getX(), v.getY());
+        return new Point2D.Double(v.getX()/norm , v.getY()/norm);
+    }
+    
+    //scale vector to size of length
+    private static Point2D scale(Point2D v, double length){
+        Point2D tmp = normalize(v);
+        return new Point2D.Double(tmp.getX()*length, tmp.getY()*length);
+    }
+    
+
+    
+    private GeneralPath subdivide2D (Point2D b0, Point2D b1, Point2D b2, Point2D b3) {
+        //set 2nd intermediate point to endpoint
+        //we could actually use another "better" point if we like to have a smoother curve
+      
+        double cutDistance = getTargetAnchorShape().getCutDistance();
+        double minDistance = cutDistance - ENDPOINT_DEVIATION;
+        /**
+         * if the cutDistance is valid the last segment of the curve
+         * gets reduced by subdivision until the distance of the endpoint(epDistance) 
+         * satisfys the condition (cutDistance > epDistance > (cutDistance - ENDPOINT-DEVIATION)
+         */
+        if(cutDistance > minDistance && minDistance > 0 ) {
+            GeneralPath path = new GeneralPath(); 
+            
+            path.moveTo(b0.getX(), b0.getY());
+            
+            CubicCurve2D.Double curve = new CubicCurve2D.Double(
+                    b0.getX(), b0.getY(), 
+                    b1.getX(), b1.getY(),
+                    b2.getX(), b2.getY(), 
+                    b3.getX(), b3.getY());
+            
+            
+           
+            CubicCurve2D right=new CubicCurve2D.Double();
+            CubicCurve2D left=new CubicCurve2D.Double();
+            curve.subdivide(left, right);   
+            double distance = b3.distance(left.getP2());
+            //if the distance is bigger as the cutDistance the left segment is added
+            //and the right segment is divided again
+            while(distance>cutDistance){                    
+                path.append(left, true);             
+                right.subdivide(left, right);
+                distance = b3.distance(left.getP2());
+                //if the devision removed to much the left segment is divided
+                while(distance < minDistance) {                            
+                    //changes the distance to ~ (distance+distance/2)
+                    left.subdivide(left, right);
+                    distance = b3.distance(left.getP2());
+                }
+            }                  
+            //append the last segment with (minDistance < distance < cutDistance)
+            path.append(left, true);         
+            return path;
+        }
+        return null;
+    }
+    
+ 
+    /**
+     * Returns whether a specified local point pL is a part of the connection 
+     * widget. 
+     * First it make a rough bounds check
+     * for Line Segments => use Super call (ConnectionWidget.isHitAt(pL)). 
+     * for self-edges => its sufficent to return getBounds.contains(pL).
+     * for Splines => Interate over all Partitial segments of the curve and make 
+     * a minmax check with the bezier points. If pL is inside the minmax 
+     * rectangle of one segment the curve is constructed and subdivided until 
+     * the distance d between center point pC (of the bounding rectangle) 
+     * and pL is below HIT_DISTANCE_SQUARE, in this case it returns true.
+     * If no no minmax check was successful or the subdivision lead to an 
+     * rectangle witch doesn`t contain pL return false. 
+     * @param localLocation the local location
+     * @return true, if the location is a part of the connection widget
+     */
+    @Override
+    public boolean isHitAt(Point localLocation) {     
+        if(!isVisible()  || !getBounds ().contains (localLocation))
+            return false;
+          
+        List<Point> controlPoints = getControlPoints ();
+        if(controlPoints.size() <=2){
+            if(isReflexive()) return true;
+            return super.isHitAt(localLocation);
+        }    
+        
+        if(bezierPoints != null) {         
+            for (int i = 0; i < bezierPoints.length-1; i+=3) {          
+                 Point2D b0 =   bezierPoints[i];
+                 Point2D b1 =   bezierPoints[i+1];
+                 Point2D b2 =   bezierPoints[i+2];
+                 Point2D b3 =   bezierPoints[i+3];
+                 
+                 CubicCurve2D left = new CubicCurve2D.Double(
+                    b0.getX(), b0.getY(), 
+                    b1.getX(), b1.getY(),
+                    b2.getX(), b2.getY(), 
+                    b3.getX(), b3.getY());
+                 
+                 
+                 Rectangle2D bounds = left.getBounds2D();
+                 while(bounds.contains(localLocation)) {                                                     
+                    //calculate the center and use HIT_DISTANCE_SQUARE for a range check  
+                    Point2D test = new Point2D.Double(bounds.getCenterX(),bounds.getCenterY());
+                    if(test.distance(localLocation) < HIT_DISTANCE_SQUARE){                        
+                        return true;
+                    }
+
+                   
+                    CubicCurve2D  right = new CubicCurve2D.Double();                    
+                    left.subdivide(left, right);
+                    Rectangle2D lb2d = left.getBounds2D();
+                    Rectangle2D rb2d = right.getBounds2D();                    
+                    if( lb2d.contains(localLocation)){      
+                        bounds = lb2d;
+                    } else if (rb2d.contains(localLocation)) {                        
+                        left = right;
+                        bounds = rb2d;
+                    } else {                       
+                        return false;
+                    }
+                    
+                 }//end while               
+            }//end for              
+        }       
+        return false;      
+    }   
+  
+ 
+}
+
+
+
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/WidgetCollisionCollector.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,12 @@
+package at.ssw.visualizer.cfg.visual;
+
+import java.util.List;
+import org.netbeans.api.visual.widget.Widget;
+
+
+public interface WidgetCollisionCollector {
+    
+    //returns a list of widgets which should be handled as obstacles
+    void collectCollisions(List<Widget> collisions);
+      
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.data" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.data.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.data-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=a403efd8
+build.xml.script.CRC32=b87f73ba
+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=a403efd8
+nbproject/build-impl.xml.script.CRC32=cc649146
+nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,33 @@
+<?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.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>at.ssw.visualizer.model.bc</package>
+                <package>at.ssw.visualizer.model.cfg</package>
+                <package>at.ssw.visualizer.model.interval</package>
+                <package>at.ssw.visualizer.model.nc</package>
+                <package>com.sun.hotspot.igv.data</package>
+                <package>com.sun.hotspot.igv.data.serialization</package>
+                <package>com.sun.hotspot.igv.data.services</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/bc/Bytecodes.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,33 @@
+package at.ssw.visualizer.model.bc;
+
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+
+/**
+ * This class holds the bytecode of a method and provides severel methods
+ * accessing the details.
+ *
+ * @author Alexander Reder
+ * @author Christian Wimmer
+ */
+public interface Bytecodes {
+    /**
+     * Back-link to the control flow graph where the bytecodes were loaded from.
+     */
+    public ControlFlowGraph getControlFlowGraph();
+
+    /**
+     * Called before the first call of getBytecodes() or getEpilogue(). Can be called multiple times.
+     */
+    public void parseBytecodes();
+    
+    /**
+     * The bytecodes of the method in the given bytecode range.
+     *
+     * @param   fromBCI starting BCI (including this bci)
+     * @param   toBCI   ending BCI (not including this bci)
+     * @return          string representation of the bytecodes
+     */
+    public String getBytecodes(int fromBCI, int toBCI);
+    
+    public String getEpilogue();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/cfg/BasicBlock.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,41 @@
+package at.ssw.visualizer.model.cfg;
+
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public interface BasicBlock {
+    public String getName();
+
+    public int getFromBci();
+
+    public int getToBci();
+
+    public List<? extends BasicBlock> getPredecessors();
+
+    public List<? extends BasicBlock> getSuccessors();
+
+    public List<? extends BasicBlock> getXhandlers();
+
+    public List<String> getFlags();
+
+    public BasicBlock getDominator();
+
+    public int getLoopIndex();
+
+    public int getLoopDepth();
+
+    public boolean hasState();
+
+    public List<State> getStates();
+
+    public boolean hasHir();
+
+    public List<IRInstruction> getHirInstructions();
+
+    public boolean hasLir();
+
+    public List<IRInstruction> getLirOperations();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/cfg/ControlFlowGraph.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,26 @@
+package at.ssw.visualizer.model.cfg;
+
+import at.ssw.visualizer.model.bc.Bytecodes;
+import at.ssw.visualizer.model.nc.NativeMethod;
+import com.sun.hotspot.igv.data.FolderElement;
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public interface ControlFlowGraph extends FolderElement {
+    public List<BasicBlock> getBasicBlocks();
+
+    public BasicBlock getBasicBlockByName(String name);
+
+    public Bytecodes getBytecodes();
+
+    public NativeMethod getNativeMethod();
+
+    public boolean hasState();
+
+    public boolean hasHir();
+
+    public boolean hasLir();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/cfg/IRInstruction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,19 @@
+package at.ssw.visualizer.model.cfg;
+
+import java.util.Collection;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public interface IRInstruction {
+    public static String HIR_NAME = "tid";
+    public static String HIR_TEXT = "instruction";
+    public static String HIR_OPERAND = "result";
+
+    public static String LIR_NUMBER = "nr";
+    public static String LIR_TEXT = "instruction";
+
+    public Collection<String> getNames();
+    public String getValue(String name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/cfg/State.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,17 @@
+package at.ssw.visualizer.model.cfg;
+
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public interface State {
+    public String getKind();
+
+    public int getSize();
+
+    public String getMethod();
+
+    public List<StateEntry> getEntries();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/cfg/StateEntry.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,19 @@
+package at.ssw.visualizer.model.cfg;
+
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public interface StateEntry {
+    public int getIndex();
+
+    public String getName();
+
+    public boolean hasPhiOperands();
+
+    public List<String> getPhiOperands();
+
+    public String getOperand();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/interval/ChildInterval.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+package at.ssw.visualizer.model.interval;
+
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public interface ChildInterval {
+    public Interval getParent();
+
+    public String getRegNum();
+
+    public String getType();
+
+    public String getOperand();
+
+    public String getSpillState();
+
+    public ChildInterval getRegisterHint();
+
+    public List<Range> getRanges();
+
+    public List<UsePosition> getUsePositions();
+
+    public int getFrom();
+
+    public int getTo();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/interval/Interval.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,19 @@
+package at.ssw.visualizer.model.interval;
+
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public interface Interval {
+    public IntervalList getParent();
+
+    public List<ChildInterval> getChildren();
+
+    public String getRegNum();
+
+    public int getFrom();
+
+    public int getTo();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/interval/IntervalList.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,16 @@
+package at.ssw.visualizer.model.interval;
+
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public interface IntervalList {
+    public List<Interval> getIntervals();
+
+    public ControlFlowGraph getControlFlowGraph();
+
+    public int getNumLIROperations();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/interval/Range.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,11 @@
+package at.ssw.visualizer.model.interval;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public interface Range {
+    public int getFrom();
+
+    public int getTo();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/interval/UsePosition.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,11 @@
+package at.ssw.visualizer.model.interval;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public interface UsePosition {
+    public char getKind();
+
+    public int getPosition();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/model/nc/NativeMethod.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,15 @@
+package at.ssw.visualizer.model.nc;
+
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+
+/**
+ *
+ * @author Alexander Reder
+ */
+public interface NativeMethod {
+
+    public ControlFlowGraph getControlFlowGraph();
+    
+    public String getMethodText();
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/bc/BytecodesImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,166 @@
+package at.ssw.visualizer.modelimpl.bc;
+
+import at.ssw.visualizer.model.bc.Bytecodes;
+import at.ssw.visualizer.model.cfg.BasicBlock;
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+import at.ssw.visualizer.modelimpl.cfg.BasicBlockImpl;
+import java.util.Arrays;
+
+/**
+ * This class holds the bytecode of a method and provides severel methods
+ * accessing the details.
+ *
+ * @author Christian Wimmer
+ */
+public class BytecodesImpl implements Bytecodes {
+    private ControlFlowGraph controlFlowGraph;
+    private String bytecodeString;
+
+    private String[] bytecodes;
+    private String epilogue;
+    
+
+    public BytecodesImpl(ControlFlowGraph controlFlowGraph, String bytecodeString) {
+        this.controlFlowGraph = controlFlowGraph;
+        this.bytecodeString = bytecodeString;
+    }
+    
+    public void parseBytecodes() {
+        String[] lines = bytecodeString.split("\n");
+
+        boolean inPrologue = true;
+        String[] result = new String[lines.length * 3];
+        int lastBci = -1;
+        int lnr = 0; 
+        for (; lnr < lines.length; lnr++) {
+            String line = lines[lnr];
+
+            line = line.trim();
+            if (line.startsWith("[")) {
+                int end = line.indexOf(']');
+                if (end != -1) {
+                    line = line.substring(end + 1, line.length());
+                }
+            }
+            
+            line = line.trim();
+            int space1 = line.indexOf(' ');
+            if (space1 <= 0) {
+                if (inPrologue) {
+                    continue;
+                } else {
+                    break;
+                }
+            }
+            String bciStr = line.substring(0, space1);
+            if (bciStr.endsWith(":")) {
+                bciStr = bciStr.substring(0, bciStr.length() - 1);
+            }
+
+            int bci;
+            try {
+                bci = Integer.parseInt(bciStr);
+            } catch (NumberFormatException ex) {
+                // Ignore invalid lines.
+                if (inPrologue) {
+                    continue;
+                } else {
+                    break;
+                }
+            }
+
+            String opcode = line.substring(space1 + 1);
+            String params = "";
+            int space2 = opcode.indexOf(' ');
+            if (space2 > 0) {
+                params = opcode.substring(space2 + 1).trim();
+                opcode = opcode.substring(0, space2);
+            }
+            String tail = "";
+            int space3 = params.indexOf('|');
+            if (space3 >= 0) {
+                tail = params.substring(space3);
+                params = params.substring(0, space3);
+            }
+
+//            if (!"ldc".equals(opcode) || !params.startsWith("\"")) {
+//                // Separate packages with "." instead of "/"
+//                params = params.replace('/', '.');
+//            }
+            
+            String printLine = bciStr + ":" + "    ".substring(Math.min(bciStr.length(), 3)) +
+                    opcode + "              ".substring(Math.min(opcode.length(), 13)) +
+                    params + "        ".substring(Math.min(params.length(), 8)) +
+                    tail;
+
+            
+            if (bci >= result.length) {
+                result = Arrays.copyOf(result, Math.max(bci + 1, result.length * 2));
+            }
+            result[bci] = printLine;
+            inPrologue = false;
+            lastBci = Math.max(lastBci, bci);
+        }
+
+        StringBuilder epilogueBuilder = new StringBuilder();
+        for (; lnr < lines.length; lnr++) {
+            epilogueBuilder.append(lines[lnr]).append("\n");
+        }
+        epilogue = epilogueBuilder.toString();
+        bytecodes = Arrays.copyOf(result, lastBci + 1);
+    
+        
+        BasicBlockImpl[] blocks = new BasicBlockImpl[bytecodes.length];
+        for (BasicBlock b : controlFlowGraph.getBasicBlocks()) {
+            if (b instanceof BasicBlockImpl) {
+                BasicBlockImpl block = (BasicBlockImpl) b;
+                if (block.getToBci() != -1) {
+                    // Do not override existing values.
+                    return;
+                }
+                if (block.getFromBci() >= 0 && block.getFromBci() < blocks.length) {
+                    blocks[block.getFromBci()] = block;
+                }
+            }
+        }
+        
+        int curToBci = -1;
+        for (int i = blocks.length - 1; i >= 0; i--) {
+            if (bytecodes[i] != null && curToBci == -1) {
+                curToBci = i;
+            }
+            if (blocks[i] != null) {
+                blocks[i].setToBci(curToBci);
+                curToBci = -1;
+            }
+        }
+    }
+    
+    public ControlFlowGraph getControlFlowGraph() {
+        return controlFlowGraph;
+    }
+
+    public String getBytecodes(int fromBCI, int toBCI) {
+        if (fromBCI < 0) {
+            return "";
+        }
+        toBCI = Math.min(toBCI, bytecodes.length);
+        StringBuilder sb = new StringBuilder();
+        for (int i = fromBCI; i < toBCI; i++) {
+            if (bytecodes[i] != null) {
+                sb.append(bytecodes[i]).append("\n");
+            }
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public String getEpilogue() {
+        return epilogue;
+    }
+
+    @Override
+    public String toString() {
+        return "Bytecodes " + getControlFlowGraph().getName();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/BasicBlockImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,143 @@
+package at.ssw.visualizer.modelimpl.cfg;
+
+import at.ssw.visualizer.model.cfg.BasicBlock;
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+import at.ssw.visualizer.model.cfg.IRInstruction;
+import at.ssw.visualizer.model.cfg.State;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public class BasicBlockImpl implements BasicBlock {
+
+    private ControlFlowGraph parent;
+    private String name;
+    private int fromBci;
+    private int toBci;
+    private BasicBlock[] predecessors;
+    private BasicBlock[] successors;
+    private BasicBlock[] xhandlers;
+    private String[] flags;
+    private BasicBlock dominator;
+    private int loopIndex;
+    private int loopDepth;
+    private int firstLirId;
+    private int lastLirId;
+    private State[] states;
+    private IRInstruction[] hirInstructions;
+    private IRInstruction[] lirOperations;
+
+    public void setValues(String name, int fromBci, int toBci, BasicBlock[] predecessors, BasicBlock[] successors, BasicBlock[] xhandlers, String[] flags, BasicBlock dominator, int loopIndex, int loopDepth, int firstLirId, int lastLirId, State[] states, IRInstruction[] hirInstructions, IRInstruction[] lirOperations) {
+        this.name = name;
+        this.fromBci = fromBci;
+        this.toBci = toBci;
+
+        this.predecessors = predecessors;
+        this.successors = successors;
+        this.xhandlers = xhandlers;
+
+        this.flags = flags;
+        this.dominator = dominator;
+        this.loopIndex = loopIndex;
+        this.loopDepth = loopDepth;
+        this.firstLirId = firstLirId;
+        this.lastLirId = lastLirId;
+
+        this.states = states;
+        this.hirInstructions = hirInstructions;
+        this.lirOperations = lirOperations;
+    }
+
+    public ControlFlowGraph getParent() {
+        return parent;
+    }
+
+    protected void setParent(ControlFlowGraph parent) {
+        this.parent = parent;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getFromBci() {
+        return fromBci;
+    }
+
+    public int getToBci() {
+        return toBci;
+    }
+
+    public void setToBci(int toBci) {
+        this.toBci = toBci;
+    }
+
+    public List<BasicBlock> getPredecessors() {
+        return Collections.unmodifiableList(Arrays.asList(predecessors));
+    }
+
+    public List<BasicBlock> getSuccessors() {
+        return Collections.unmodifiableList(Arrays.asList(successors));
+    }
+
+    public List<BasicBlock> getXhandlers() {
+        return Collections.unmodifiableList(Arrays.asList(xhandlers));
+    }
+
+    public List<String> getFlags() {
+        return Collections.unmodifiableList(Arrays.asList(flags));
+    }
+
+    public BasicBlock getDominator() {
+        return dominator;
+    }
+
+    public int getLoopIndex() {
+        return loopIndex;
+    }
+
+    public int getLoopDepth() {
+        return loopDepth;
+    }
+
+    public int getFirstLirId() {
+        return firstLirId;
+    }
+
+    public int getLastLirId() {
+        return lastLirId;
+    }
+
+    public boolean hasState() {
+        return states != null;
+    }
+
+    public List<State> getStates() {
+        return Collections.unmodifiableList(Arrays.asList(states));
+    }
+
+    public boolean hasHir() {
+        return hirInstructions != null;
+    }
+
+    public List<IRInstruction> getHirInstructions() {
+        return Collections.unmodifiableList(Arrays.asList(hirInstructions));
+    }
+
+    public boolean hasLir() {
+        return lirOperations != null;
+    }
+
+    public List<IRInstruction> getLirOperations() {
+        return Collections.unmodifiableList(Arrays.asList(lirOperations));
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/IRInstructionImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,40 @@
+package at.ssw.visualizer.modelimpl.cfg;
+
+import at.ssw.visualizer.model.cfg.IRInstruction;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+
+public class IRInstructionImpl implements IRInstruction {
+    private LinkedHashMap<String, String> data;
+
+    public IRInstructionImpl(LinkedHashMap<String, String> data) {
+        this.data = data;
+    }
+
+    public IRInstructionImpl(String pinned, int bci, int useCount, String name, String text, String operand) {
+        data = new LinkedHashMap<String, String>();
+        data.put("p", pinned);
+        data.put("bci", Integer.toString(bci));
+        data.put("use", Integer.toString(useCount));
+        data.put(HIR_NAME, name);
+        if (operand != null) {
+            data.put(HIR_OPERAND, operand);
+        }
+        data.put(HIR_TEXT, text);
+    }
+
+    public IRInstructionImpl(int number, String text) {
+        data = new LinkedHashMap<String, String>();
+        data.put(LIR_NUMBER, Integer.toString(number));
+        data.put(LIR_TEXT, text);
+    }
+
+    public Collection<String> getNames() {
+        return Collections.unmodifiableSet(data.keySet());
+    }
+
+    public String getValue(String name) {
+        return data.get(name);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/StateEntryImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,44 @@
+package at.ssw.visualizer.modelimpl.cfg;
+
+import at.ssw.visualizer.model.cfg.StateEntry;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public class StateEntryImpl implements StateEntry {
+    private int index;
+    private String name;
+    private String[] phiOperands;
+    private String operand;
+
+    public StateEntryImpl(int index, String name, String[] phiOperands, String operand) {
+        this.index = index;
+        this.name = name;
+        this.phiOperands = phiOperands;
+        this.operand = operand;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public boolean hasPhiOperands() {
+        return phiOperands != null;
+    }
+
+    public List<String> getPhiOperands() {
+        return Collections.unmodifiableList(Arrays.asList(phiOperands));
+    }
+
+    public String getOperand() {
+        return operand;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/StateImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,41 @@
+package at.ssw.visualizer.modelimpl.cfg;
+
+import at.ssw.visualizer.model.cfg.State;
+import at.ssw.visualizer.model.cfg.StateEntry;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public class StateImpl implements State {
+    private String kind;
+    private int size;
+    private String method;
+    private StateEntry[] entries;
+
+    public StateImpl(String kind, int size, String method, StateEntryImpl[] entries) {
+        this.kind = kind;
+        this.size = size;
+        this.method = method;
+        this.entries = entries;
+    }
+
+    public String getKind() {
+        return kind;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public String getMethod() {
+        return method;
+    }
+
+    public List<StateEntry> getEntries() {
+        return Collections.unmodifiableList(Arrays.asList(entries));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/ChildIntervalImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,118 @@
+package at.ssw.visualizer.modelimpl.interval;
+
+import at.ssw.visualizer.model.interval.ChildInterval;
+import at.ssw.visualizer.model.interval.Interval;
+import at.ssw.visualizer.model.interval.Range;
+import at.ssw.visualizer.model.interval.UsePosition;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public class ChildIntervalImpl implements ChildInterval, Comparable<ChildIntervalImpl> {
+    private Interval parent;
+    private String regNum;
+    private String type;
+    private String operand;
+    private String spillState;
+    private ChildInterval registerHint;
+    private Range[] ranges;
+    private UsePosition[] usePositions;
+
+    public void setValues(String regNum, String type, String operand, String spillState, ChildInterval registerHint, Range[] ranges, UsePosition[] usePositions) {
+        this.regNum = regNum;
+        this.type = type;
+        this.operand = operand;
+        this.spillState = spillState;
+        this.registerHint = registerHint;
+        this.ranges = ranges;
+        this.usePositions = usePositions;
+    }
+    
+    public Interval getParent() {
+        return parent;
+    }
+
+    protected void setParent(IntervalImpl parent) {
+        this.parent = parent;
+    }
+
+    public String getRegNum() {
+        return regNum;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getOperand() {
+        return operand;
+    }
+
+    public String getSpillState() {
+        return spillState;
+    }
+
+    public ChildInterval getRegisterHint() {
+        return registerHint;
+    }
+
+    public List<Range> getRanges() {
+        return Collections.unmodifiableList(Arrays.asList(ranges));
+    }
+
+    public List<UsePosition> getUsePositions() {
+        return Collections.unmodifiableList(Arrays.asList(usePositions));
+    }
+
+
+    public int getFrom() {
+        return ranges[0].getFrom();
+    }
+
+    public int getTo() {
+        return ranges[ranges.length - 1].getTo();
+    }
+
+
+    public int compareTo(ChildIntervalImpl other) {
+        return getFrom() - other.getFrom();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder result = new StringBuilder();
+        result.append(regNum);
+        result.append(": ");
+        result.append(getType());
+        result.append(", ");
+        result.append(getOperand());
+        result.append(", ");
+        if (registerHint != null) {
+            result.append(registerHint.getRegNum());
+        } else {
+            result.append("null");
+        }
+
+        result.append("  ");
+        for (int i = 0; i < ranges.length; i++) {
+            if (i > 0) {
+                result.append(", ");
+            }
+            result.append(ranges[i]);
+        }
+
+        result.append("  ");
+        for (int i = 0; i < usePositions.length; i++) {
+            if (i > 0) {
+                result.append(", ");
+            }
+            result.append(usePositions[i]);
+        }
+
+        return result.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/IntervalImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,60 @@
+package at.ssw.visualizer.modelimpl.interval;
+
+import at.ssw.visualizer.model.interval.ChildInterval;
+import at.ssw.visualizer.model.interval.Interval;
+import at.ssw.visualizer.model.interval.IntervalList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public class IntervalImpl implements Interval {
+    private IntervalList parent;
+    private ChildInterval[] children;
+
+    public IntervalImpl(ChildIntervalImpl[] children) {
+        this.children = children;
+        for (ChildIntervalImpl child : children) {
+            child.setParent(this);
+        }
+    }
+
+    public IntervalList getParent() {
+        return parent;
+    }
+
+    protected void setParent(IntervalListImpl parent) {
+        this.parent = parent;
+    }
+
+    public List<ChildInterval> getChildren() {
+        return Collections.unmodifiableList(Arrays.asList(children));
+    }
+
+    public String getRegNum() {
+        return children[0].getRegNum();
+    }
+
+    public int getFrom() {
+        return children[0].getFrom();
+    }
+
+    public int getTo() {
+        return children[children.length - 1].getTo();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder result = new StringBuilder();
+        for (int i = 0; i < children.length; i++) {
+            if (i > 0) {
+                result.append("\n  ");
+            }
+            result.append(children[i]);
+        }
+        return result.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/IntervalListImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,54 @@
+package at.ssw.visualizer.modelimpl.interval;
+
+import at.ssw.visualizer.model.cfg.BasicBlock;
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+import at.ssw.visualizer.model.interval.Interval;
+import at.ssw.visualizer.model.interval.IntervalList;
+import com.sun.hotspot.igv.data.AbstractFolderElement;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public class IntervalListImpl extends AbstractFolderElement implements IntervalList {
+    private Interval[] intervals;
+    private ControlFlowGraph controlFlowGraph;
+    private int numLIROperations;
+
+    public IntervalListImpl(String shortName, String name, IntervalImpl[] intervals, ControlFlowGraph controlFlowGraph) {
+        super(shortName, name);
+        this.intervals = intervals;
+        this.controlFlowGraph = controlFlowGraph;
+
+        for (IntervalImpl interval : intervals) {
+            interval.setParent(this);
+            numLIROperations = Math.max(numLIROperations, interval.getTo());
+        }
+//        for (BasicBlock basicBlock : controlFlowGraph.getBasicBlocks()) {
+//            numLIROperations = Math.max(numLIROperations, basicBlock.getLastLirId() + 2);
+//        }
+        // TODO(tw): Add number of LIR operations to output.
+    }
+
+
+    public List<Interval> getIntervals() {
+        return Collections.unmodifiableList(Arrays.asList(intervals));
+    }
+
+    public ControlFlowGraph getControlFlowGraph() {
+        return controlFlowGraph;
+    }
+
+    public int getNumLIROperations() {
+        return numLIROperations;
+    }
+
+
+    @Override
+    public String toString() {
+        return "    Intervals \"" + getName() + "\": " + intervals.length + " intervals\n";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/RangeImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,36 @@
+package at.ssw.visualizer.modelimpl.interval;
+
+import at.ssw.visualizer.model.interval.Range;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public class RangeImpl implements Range, Comparable<RangeImpl> {
+    private int from;
+    private int to;
+
+    public RangeImpl(int from, int to) {
+        this.from = from;
+        this.to = to;
+    }
+
+
+    public int getFrom() {
+        return from;
+    }
+
+    public int getTo() {
+        return to;
+    }
+
+
+    public int compareTo(RangeImpl other) {
+        return getFrom() - other.getFrom();
+    }
+
+    @Override
+    public String toString() {
+        return "[" + from + ", " + to + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/UsePositionImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,36 @@
+package at.ssw.visualizer.modelimpl.interval;
+
+import at.ssw.visualizer.model.interval.UsePosition;
+
+/**
+ *
+ * @author Christian Wimmer
+ */
+public class UsePositionImpl implements UsePosition, Comparable<UsePositionImpl> {
+    private int position;
+    private char kind;
+
+    public UsePositionImpl(int position, char kind) {
+        this.position = position;
+        this.kind = kind;
+    }
+
+
+    public char getKind() {
+        return kind;
+    }
+
+    public int getPosition() {
+        return position;
+    }
+
+
+    public int compareTo(UsePositionImpl other) {
+        return getPosition() - other.getPosition();
+    }
+
+    @Override
+    public String toString() {
+        return position + "(" + kind + ")";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/nc/NativeMethodImpl.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,28 @@
+package at.ssw.visualizer.modelimpl.nc;
+
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+import at.ssw.visualizer.model.nc.NativeMethod;
+
+/**
+ *
+ * @author Alexander Reder
+ */
+public class NativeMethodImpl implements NativeMethod {
+
+    private ControlFlowGraph controlFlowGraph;
+    private String methodText;
+    
+    public NativeMethodImpl(ControlFlowGraph controlFlowGraph, String methodText) {
+        this.controlFlowGraph = controlFlowGraph;
+        this.methodText = methodText;
+    }
+
+    public ControlFlowGraph getControlFlowGraph() {
+        return controlFlowGraph;
+    }
+    
+    public String getMethodText() {
+        return methodText;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/AbstractFolderElement.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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;
+
+public class AbstractFolderElement implements FolderElement {
+    
+    private String name;
+    private String shortName;
+    private Folder parent;
+    
+    public AbstractFolderElement(String name, String shortName) {
+        this.name = name;
+        this.shortName = shortName;
+    }
+
+    public String getShortName() {
+        return shortName;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public Folder getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(Folder parent) {
+        this.parent = parent;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Data
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/ChangedEvent.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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 class ChangedEvent<T> extends Event<ChangedListener<T>> {
+
+    private T object;
+
+    public ChangedEvent(T object) {
+        this.object = object;
+    }
+
+    @Override
+    protected void fire(ChangedListener<T> l) {
+        l.changed(object);
+    }
+
+    public void changeObject(T newObject) {
+        if (object != newObject) {
+            this.object = newObject;
+            fire();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/ChangedEventProvider.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,38 @@
+/*
+ * 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.data;
+
+/**
+ * Provides a changed event object.
+ * @author Thomas Wuerthinger
+ * @param <T> Class for which the changed event fires.
+ */
+public interface ChangedEventProvider<T> {
+
+    /**
+     * Returns the changed event object. Should always return the same instance.
+     */
+    ChangedEvent<T> getChangedEvent();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/ChangedListener.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Listens to changed events.
+ * @author Thomas Wuerthinger
+ * @param <T> Class for which the changed event fires.
+ */
+public interface ChangedListener<T> {
+
+    /**
+     * 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/visualizer/Data/src/com/sun/hotspot/igv/data/ControllableChangedListener.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+/**
+ *
+ * @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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Event.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,87 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public abstract class Event<L> {
+
+    private List<L> listener;
+    private boolean fireEvents;
+    private boolean eventWasFired;
+    
+    public Event() {
+        listener = new ArrayList<>();
+        fireEvents = true;
+    }
+
+    public void addListener(L l) {
+        listener.add(l);
+    }
+
+    public void addListenerAndFire(L l) {
+        addListener(l);
+        fire(l);
+    }
+
+    /**
+     * Remove listener
+     * @param l
+     */
+    public void removeListener(final L l) {
+        listener.remove(l);
+    }
+
+    public void fire() {
+        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();
+        }
+    }
+    
+    protected abstract void fire(L l);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Folder.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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 {
+    String getName();
+    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/visualizer/Data/src/com/sun/hotspot/igv/data/FolderElement.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,98 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class GraphDocument extends Properties.Entity implements ChangedEventProvider<GraphDocument>, Folder {
+
+    private List<FolderElement> elements;
+    private ChangedEvent<GraphDocument> changedEvent;
+
+    public GraphDocument() {
+        elements = new ArrayList<>();
+        changedEvent = new ChangedEvent<>(this);
+    }
+
+    public void clear() {
+        elements.clear();
+        getChangedEvent().fire();
+    }
+
+    @Override
+    public ChangedEvent<GraphDocument> getChangedEvent() {
+        return changedEvent;
+    }
+
+    public void addGraphDocument(GraphDocument document) {
+        for (FolderElement e : document.elements) {
+            e.setParent(this);
+            this.addElement(e);
+        }
+        document.clear();
+        getChangedEvent().fire();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+
+        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);
+        element.setParent(this);
+        getChangedEvent().fire();
+    }
+
+    @Override
+    public String getName() {
+        return "root";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Group.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,180 @@
+/*
+ * 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;
+
+import java.util.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Group extends Properties.Entity implements ChangedEventProvider<Group>, Folder, FolderElement {
+
+    private final List<FolderElement> elements;
+    private final List<InputGraph> graphs;
+
+    private InputMethod method;
+    private transient ChangedEvent<Group> changedEvent;
+    private Folder parent;
+
+    public Group(Folder parent) {
+        elements = new ArrayList<>();
+        graphs = new ArrayList<>();
+        changedEvent = new ChangedEvent<>(this);
+        this.parent = parent;
+
+        // Ensure that name and type are never null
+        getProperties().setProperty("name", "");
+        getProperties().setProperty("type", "");
+    }
+
+    public void fireChangedEvent() {
+        changedEvent.fire();
+    }
+
+    public void setMethod(InputMethod method) {
+        this.method = method;
+    }
+
+    public InputMethod getMethod() {
+        return method;
+    }
+
+    @Override
+    public ChangedEvent<Group> getChangedEvent() {
+        return changedEvent;
+    }
+
+    @Override
+    public List<FolderElement> getElements() {
+        return Collections.unmodifiableList(elements);
+    }
+
+    public int getGraphsCount() {
+        return elements.size();
+    }
+    
+    @Override
+    public void addElement(FolderElement element) {
+        elements.add(element);
+        if (element instanceof InputGraph) {
+            graphs.add((InputGraph) element);
+        } else {
+            
+        }
+        element.setParent(this);
+        changedEvent.fire();
+    }
+
+    public Set<Integer> getAllNodes() {
+        Set<Integer> result = new HashSet<>();
+        for (FolderElement e : elements) {
+            if (e instanceof InputGraph) {
+                InputGraph g = (InputGraph) e;
+                result.addAll(g.getNodesAsSet());
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Group ").append(getProperties()).append("\n");
+        for (FolderElement g : elements) {
+            sb.append(g.toString());
+            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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,205 @@
+/*
+ * 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;
+
+import at.ssw.visualizer.model.cfg.BasicBlock;
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+import at.ssw.visualizer.model.cfg.IRInstruction;
+import at.ssw.visualizer.model.cfg.State;
+import java.util.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InputBlock implements BasicBlock {
+
+    private List<InputNode> nodes;
+    private String name;
+    private InputGraph graph;
+    private List<InputBlock> successors;
+    private List<InputBlock> predecessors;
+
+    @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;
+        }
+        
+        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<>();
+        successors = new ArrayList<>();
+        predecessors = new ArrayList<>();
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    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);
+        final InputNode node = graph.getNode(id);
+        assert node != null;
+        assert !nodes.contains(node) : "duplicate : " + node;
+        nodes.add(node);
+    }
+
+    @Override
+    public List<InputBlock> getSuccessors() {
+        return Collections.unmodifiableList(successors);
+    }
+
+    @Override
+    public String toString() {
+        return "Block " + this.getName();
+    }
+
+    void addSuccessor(InputBlock b) {
+        if (!successors.contains(b)) {
+            successors.add(b);
+            b.predecessors.add(this);
+        }
+    }
+
+    @Override
+    public int getFromBci() {
+        // TODO(tw): Implement.
+        return -1;
+    }
+
+    @Override
+    public int getToBci() {
+        // TODO(tw): Implement.
+        return -1;
+    }
+
+    @Override
+    public List<InputBlock> getPredecessors() {
+        return Collections.unmodifiableList(predecessors);
+    }
+
+    @Override
+    public List<BasicBlock> getXhandlers() {
+        // TODO(tw): Implement.
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<String> getFlags() {
+        // TODO(tw): Implement.
+        return Collections.emptyList();
+    }
+
+    @Override
+    public BasicBlock getDominator() {
+        // TODO(tw): Implement.
+        return null;
+    }
+
+    @Override
+    public int getLoopIndex() {
+        // TODO(tw): Implement.
+        return -1;
+    }
+
+    @Override
+    public int getLoopDepth() {
+        // TODO(tw): Implement.
+        return -1;
+    }
+
+    @Override
+    public boolean hasState() {
+        // TODO(tw): Implement.
+        return false;
+    }
+
+    @Override
+    public List<State> getStates() {
+        // TODO(tw): Implement.
+        return Collections.emptyList();
+    }
+
+    @Override
+    public boolean hasHir() {
+        // TODO(tw): Implement.
+        return false;
+    }
+
+    @Override
+    public List<IRInstruction> getHirInstructions() {
+        // TODO(tw): Implement.
+        return Collections.emptyList();
+    }
+
+    @Override
+    public boolean hasLir() {
+        // TODO(tw): Implement.
+        return false;
+    }
+
+    @Override
+    public List<IRInstruction> getLirOperations() {
+        // TODO(tw): Implement.
+        return Collections.emptyList();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputBlockEdge.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.data;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+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;
+        assert to != null;
+        this.from = from;
+        this.to = to;
+    }
+
+    public InputBlock getFrom() {
+        return from;
+    }
+
+    public InputBlock getTo() {
+        return to;
+    }
+
+    public State getState() {
+        return state;
+    }
+
+    public void setState(State state) {
+        this.state = state;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj != null && obj instanceof InputBlockEdge) {
+            InputBlockEdge e = (InputBlockEdge) obj;
+            return e.from.equals(from) && e.to.equals(to);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = from.hashCode();
+        hash = 59 * hash + to.hashCode();
+        return hash;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InputBytecode {
+
+    private int bci;
+    private String name;
+    private InputMethod inlined;
+
+    public InputBytecode(int bci, String name) {
+        this.bci = bci;
+        this.name = name;
+    }
+
+    public InputMethod getInlined() {
+        return inlined;
+    }
+
+    public void setInlined(InputMethod inlined) {
+        this.inlined = inlined;
+    }
+
+    public int getBci() {
+        return bci;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,138 @@
+/*
+ * 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;
+
+import java.util.Comparator;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InputEdge {
+
+    public enum State {
+
+        SAME,
+        NEW,
+        DELETED
+    }
+    
+    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 char toIndex;
+    private char fromIndex;
+    private int from;
+    private int to;
+    private State state;
+    private String label;
+
+    public InputEdge(char toIndex, int from, int to) {
+        this((char) 0, toIndex, from, to, null);
+    }
+
+    public InputEdge(char fromIndex, char toIndex, int from, int to) {
+        this(fromIndex, toIndex, from, to, null);
+    }
+
+    public InputEdge(char fromIndex, char toIndex, int from, int to, String label) {
+        this.toIndex = toIndex;
+        this.fromIndex = fromIndex;
+        this.from = from;
+        this.to = to;
+        this.state = State.SAME;
+        this.label = label;
+    }
+
+    public State getState() {
+        return state;
+    }
+
+    public void setState(State x) {
+        this.state = x;
+    }
+
+    public char getToIndex() {
+        return toIndex;
+    }
+    
+    public char getFromIndex() {
+        return fromIndex;
+    }
+
+    public String getName() {
+        return "in" + toIndex;
+    }
+
+    public int getFrom() {
+        return from;
+    }
+
+    public int getTo() {
+        return to;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !(o instanceof InputEdge)) {
+            return false;
+        }
+        InputEdge conn2 = (InputEdge) o;
+        return conn2.fromIndex == fromIndex && conn2.toIndex == toIndex && conn2.from == from && conn2.to == to;
+    }
+
+    @Override
+    public String toString() {
+        return "Edge from " + from + " to " + to + "(" + (int) fromIndex + ", " + (int) toIndex + ") ";
+    }
+
+    @Override
+    public int hashCode() {
+        return (from << 20 | to << 8 | toIndex << 4 | fromIndex);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,340 @@
+/*
+ * 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;
+
+import at.ssw.visualizer.model.bc.Bytecodes;
+import at.ssw.visualizer.model.cfg.BasicBlock;
+import at.ssw.visualizer.model.cfg.ControlFlowGraph;
+import at.ssw.visualizer.model.nc.NativeMethod;
+import java.util.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InputGraph extends Properties.Entity implements FolderElement, ControlFlowGraph {
+
+    private Map<Integer, InputNode> nodes;
+    private Set<InputEdge> edges;
+    private Folder parent;
+    private Group parentGroup;
+    private Map<String, InputBlock> blocks;
+    private Set<InputBlockEdge> blockEdges;
+    private Map<Integer, InputBlock> nodeToBlock;
+
+    public InputGraph(String name) {
+        setName(name);
+        nodes = new LinkedHashMap<>();
+        edges = new LinkedHashSet<>();
+        blocks = new LinkedHashMap<>();
+        blockEdges = new LinkedHashSet<>();
+        nodeToBlock = new LinkedHashMap<>();
+    }
+    
+    @Override
+    public void setParent(Folder parent) {
+        this.parent = parent;
+        if (parent instanceof Group) {
+            assert this.parentGroup == null;
+            this.parentGroup = (Group) parent;
+        }
+    }
+
+    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 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;
+    }
+    
+    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 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";
+        
+        InputEdge edge = new InputEdge((char)fromIndex, (char)toIndex, from, to);
+        if(!this.getEdges().contains(edge)) {
+            this.addEdge(edge);
+        }
+    }
+
+    public void ensureNodesInBlocks() {
+        InputBlock noBlock = null;
+        Set<InputNode> scheduledNodes = new HashSet<>();
+
+        for (InputBlock b : getBlocks()) {
+            for (InputNode n : b.getNodes()) {
+                assert !scheduledNodes.contains(n);
+                scheduledNodes.add(n);
+            }
+        }
+
+        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());
+            }
+            assert this.getBlock(n) != null;
+        }
+    }
+
+    public void setBlock(InputNode node, InputBlock block) {
+        nodeToBlock.put(node.getId(), block);
+    }
+
+    public InputBlock getBlock(int nodeId) {
+        return nodeToBlock.get(nodeId);
+    }
+
+    public InputBlock getBlock(InputNode node) {
+        assert nodes.containsKey(node.getId());
+        assert nodes.get(node.getId()).equals(node);
+        return getBlock(node.getId());
+    }
+
+    public InputGraph getNext() {
+        return parentGroup.getNext(this);
+    }
+
+    public InputGraph getPrev() {
+        return parentGroup.getPrev(this);
+    }
+
+    private void setName(String name) {
+        this.getProperties().setProperty("name", name);
+    }
+
+    @Override
+    public String getName() {
+        return getProperties().get("name");
+    }
+
+    public Collection<InputNode> getNodes() {
+        return Collections.unmodifiableCollection(nodes.values());
+    }
+
+    public Set<Integer> getNodesAsSet() {
+        return Collections.unmodifiableSet(nodes.keySet());
+    }
+
+    public Collection<InputBlock> getBlocks() {
+        return Collections.unmodifiableCollection(blocks.values());
+    }
+
+    public void addNode(InputNode node) {
+        nodes.put(node.getId(), node);
+    }
+
+    public InputNode getNode(int id) {
+        return nodes.get(id);
+    }
+
+    public InputNode removeNode(int index) {
+        return nodes.remove(index);
+    }
+
+    public Collection<InputEdge> getEdges() {
+        return Collections.unmodifiableSet(edges);
+    }
+
+    public void removeEdge(InputEdge c) {
+        boolean removed = edges.remove(c);
+        assert removed;
+    }
+
+    public void addEdge(InputEdge c) {
+        // Be tolerant with duplicated edges.
+        if (!edges.contains(c)) {
+            edges.add(c);
+        }
+    }
+
+    public Group getGroup() {
+        return parentGroup;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Graph ").append(getName()).append(" ").append(getProperties().toString()).append("\n");
+        for (InputNode n : nodes.values()) {
+            sb.append(n.toString());
+            sb.append("\n");
+        }
+
+        for (InputEdge c : edges) {
+            sb.append(c.toString());
+            sb.append("\n");
+        }
+
+        for (InputBlock b : getBlocks()) {
+            sb.append(b.toString());
+            sb.append("\n");
+        }
+
+        return sb.toString();
+    }
+
+    public InputBlock addBlock(String name) {
+        final InputBlock b = new InputBlock(this, name);
+        blocks.put(b.getName(), b);
+        return b;
+    }
+
+    public InputBlock getBlock(String s) {
+        return blocks.get(s);
+    }
+
+    public Collection<InputBlockEdge> getBlockEdges() {
+        return Collections.unmodifiableSet(blockEdges);
+    }
+
+    @Override
+    public Folder getParent() {
+        return parent;
+    }
+
+    @Override
+    public List<BasicBlock> getBasicBlocks() {
+        return new ArrayList<BasicBlock>(blocks.values());
+    }
+
+    @Override
+    public BasicBlock getBasicBlockByName(String name) {
+        return blocks.get(name);
+    }
+
+    @Override
+    public Bytecodes getBytecodes() {
+        // TODO(tw): no bytecodes
+        return null;
+    }
+
+    @Override
+    public NativeMethod getNativeMethod() {
+        // TODO(tw): No native method.
+        return null;
+    }
+
+    @Override
+    public boolean hasState() {
+        // TODO(tw): implement
+        return false;
+    }
+
+    @Override
+    public boolean hasHir() {
+        // TODO(tw): Implement
+        return false;
+    }
+
+    @Override
+    public boolean hasLir() {
+        // TODO(tw): Implement
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,149 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InputMethod extends Properties.Entity {
+
+    private String name;
+    private int bci;
+    private String shortName;
+    private List<InputMethod> inlined;
+    private InputMethod parentMethod;
+    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<>();
+        bytecodes = new ArrayList<>();
+    }
+
+    public List<InputBytecode> getBytecodes() {
+        return Collections.unmodifiableList(bytecodes);
+    }
+
+    public List<InputMethod> getInlined() {
+        return Collections.unmodifiableList(inlined);
+    }
+
+    public void addInlined(InputMethod m) {
+
+        // assert bci unique
+        for (InputMethod m2 : inlined) {
+            assert m2.getBci() != m.getBci();
+        }
+
+        inlined.add(m);
+        assert m.parentMethod == null;
+        m.parentMethod = this;
+
+        for (InputBytecode bc : bytecodes) {
+            if (bc.getBci() == m.getBci()) {
+                bc.setInlined(m);
+            }
+        }
+    }
+
+    public Group getGroup() {
+        return group;
+    }
+
+    public String getShortName() {
+        return shortName;
+    }
+
+    public void setBytecodes(String text) {
+
+        String[] strings = text.split("\n");
+        int oldNumber = -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());
+
+                int number = -1;
+                number = Integer.parseInt(numberString);
+
+                // assert correct order of bytecodes
+                assert number > oldNumber;
+
+                InputBytecode bc = new InputBytecode(number, tmpName);
+                bytecodes.add(bc);
+
+                for (InputMethod m : inlined) {
+                    if (m.getBci() == number) {
+                        bc.setInlined(m);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getBci() {
+        return bci;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,102 @@
+/*
+ * 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;
+
+import java.util.Comparator;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InputNode extends Properties.Entity {
+
+    private int id;
+
+    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);
+        setId(n.id);
+    }
+
+    public InputNode(int id) {
+        setId(id);
+    }
+
+    public void setId(int id) {
+        this.id = id;
+        getProperties().setProperty("id", "" + id);
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof InputNode)) {
+            return false;
+        }
+        InputNode n = (InputNode) o;
+        return n.id == id;
+    }
+
+    @Override
+    public int hashCode() {
+        return id * 13;
+    }
+
+    @Override
+    public String toString() {
+        return "Node " + id + " " + getProperties().toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Pair.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,87 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Pair<L, R> {
+
+    private L l;
+    private R r;
+
+    public Pair() {
+    }
+
+    public Pair(L l, R r) {
+        this.l = l;
+        this.r = r;
+    }
+
+    public L getLeft() {
+        return l;
+    }
+
+    public void setLeft(L l) {
+        this.l = l;
+    }
+
+    public R getRight() {
+        return r;
+    }
+
+    public void setRight(R r) {
+        this.r = r;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !(o instanceof Pair)) {
+            return false;
+        }
+        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 == null) ? 0 : l.hashCode()) * 71 + ((r == null) ? 0 : r.hashCode());
+    }
+
+    @Override
+    public String toString() {
+        return "[" + l + "/" + r + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Properties.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,391 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Properties implements Serializable, Iterable<Property> {
+
+    public static final long serialVersionUID = 1L;
+    private String[] map = new String[4];
+
+    public Properties() {
+    }
+
+    @Override
+    public boolean equals(java.lang.Object o) {
+        if (!(o instanceof Properties)) {
+            return false;
+        }
+
+        Properties p = (Properties) o;
+
+        for (Property prop : this) {
+            String value = p.get(prop.getName());
+            if (value == null || !value.equals(prop.getValue())) {
+                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;
+
+        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;
+    }
+
+    public Properties(String name, String value) {
+        this();
+        this.setProperty(name, value);
+    }
+
+    public Properties(String name, String value, String name1, String value1) {
+        this(name, value);
+        this.setProperty(name1, value1);
+    }
+
+    public Properties(String name, String value, String name1, String value1, String name2, String value2) {
+        this(name, value, name1, value1);
+        this.setProperty(name2, value2);
+    }
+
+    public Properties(Properties p) {
+        map = new String[p.map.length];
+        System.arraycopy(p.map, 0, map, 0, p.map.length);
+    }
+
+    public static class Entity implements Provider {
+
+        private Properties properties;
+
+        public Entity() {
+            properties = new Properties();
+        }
+
+        public Entity(Properties.Entity object) {
+            properties = new Properties(object.getProperties());
+        }
+
+        @Override
+        public Properties getProperties() {
+            return properties;
+        }
+    }
+
+    public interface PropertyMatcher {
+
+        String getName();
+
+        boolean match(String value);
+    }
+
+    public static class InvertPropertyMatcher implements PropertyMatcher {
+
+        private PropertyMatcher matcher;
+
+        public InvertPropertyMatcher(PropertyMatcher matcher) {
+            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);
+        }
+    }
+
+    public static class StringPropertyMatcher implements PropertyMatcher {
+
+        private String name;
+        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);
+        }
+    }
+
+    public static class RegexpPropertyMatcher implements PropertyMatcher {
+
+        private String name;
+        private Pattern valuePattern;
+        
+        public RegexpPropertyMatcher(String name, String 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 && name.equals(map[i])) {
+                value = map[i + 1];
+                break;
+            }
+        }
+        if (value != null && matcher.match(value)) {
+            return new Property(name, value);
+        } else {
+            return null;
+        }
+    }
+
+    public interface Provider {
+
+        public Properties getProperties();
+    }
+
+    @Override
+    public String toString() {
+        List<String[]> pairs = new ArrayList<>();
+        for (int i = 0; i < map.length; i += 2) {
+            if (map[i + 1] != null) {
+                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] + "=" + p[1]);
+        }
+        return sb.append("]").toString();
+    }
+
+    public static class PropertySelector<T extends Properties.Provider> {
+
+        private Collection<T> objects;
+
+        public PropertySelector(Collection<T> objects) {
+            this.objects = objects;
+        }
+
+        public T selectSingle(PropertyMatcher matcher) {
+
+            for (T t : objects) {
+                Property p = t.getProperties().selectSingle(matcher);
+                if (p != null) {
+                    return t;
+                }
+            }
+
+            return null;
+        }
+
+        public List<T> selectMultiple(PropertyMatcher matcher) {
+            List<T> result = new ArrayList<>();
+
+            for (T t : objects) {
+                Property p = t.getProperties().selectSingle(matcher);
+                if (p != null) {
+                    result.add(t);
+                }
+            }
+
+            return result;
+        }
+    }
+
+    public String get(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 void setProperty(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];
+                if (value == null) {
+                    // remove this property
+                    map[i] = null;
+                    map[i + 1] = null;
+                } else {
+                    map[i + 1] = value;
+                }
+                return;
+            }
+        }
+        if (value == null) {
+            return;
+        }
+        for (int i = 0; i < map.length; i += 2) {
+            if (map[i] == null) {
+                map[i] = name;
+                map[i + 1] = value;
+                return;
+            }
+        }
+        String[] newMap = new String[map.length + 4];
+        System.arraycopy(map, 0, newMap, 0, map.length);
+        newMap[map.length] = name;
+        newMap[map.length + 1] = value;
+        map = newMap;
+    }
+
+    public void add(Properties properties) {
+        for (Property p : properties) {
+            setProperty(p.getName(), p.getValue());
+        }
+    }
+
+    private class PropertiesIterator implements Iterator<Property> {
+
+        int index;
+
+        @Override
+        public boolean hasNext() {
+            while (index < map.length && map[index + 1] == null) {
+                index += 2;
+            }
+            return index < map.length;
+        }
+
+        @Override
+        public Property next() {
+            if (index < map.length) {
+                index += 2;
+                return new Property(map[index - 2], map[index - 1]);
+            }
+            return null;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+    }
+
+    @Override
+    public Iterator<Property> iterator() {
+        return new PropertiesIterator();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Property.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,77 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Property implements Serializable {
+
+    public static final long serialVersionUID = 1L;
+    private String name;
+    private 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() {
+        return name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    @Override
+    public String toString() {
+        return name + "=" + value;
+    }
+
+    @Override
+    public boolean equals(Object 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() * 13 + value.hashCode();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Source.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+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/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,542 @@
+/*
+ * 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.serialization;
+
+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.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.XMLReader;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Parser {
+
+    public static final String INDENT = "  ";
+    public static final String TOP_ELEMENT = "graphDocument";
+    public static final String GROUP_ELEMENT = "group";
+    public static final String GRAPH_ELEMENT = "graph";
+    public static final String ROOT_ELEMENT = "graphDocument";
+    public static final String PROPERTIES_ELEMENT = "properties";
+    public static final String EDGES_ELEMENT = "edges";
+    public static final String PROPERTY_ELEMENT = "p";
+    public static final String EDGE_ELEMENT = "edge";
+    public static final String NODE_ELEMENT = "node";
+    public static final String NODES_ELEMENT = "nodes";
+    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";
+    public static final String NODE_NAME_PROPERTY = "name";
+    public static final String EDGE_NAME_PROPERTY = "name";
+    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 PROPERTY_NAME_PROPERTY = "name";
+    public static final String GRAPH_NAME_PROPERTY = "name";
+    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";
+    public static final String METHOD_BCI_PROPERTY = "bci";
+    public static final String METHOD_SHORT_NAME_PROPERTY = "shortName";
+    public static final String CONTROL_FLOW_ELEMENT = "controlFlow";
+    public static final String BLOCK_NAME_PROPERTY = "name";
+    public static final String BLOCK_ELEMENT = "block";
+    public static final String SUCCESSORS_ELEMENT = "successors";
+    public static final String SUCCESSOR_ELEMENT = "successor";
+    public static final String ASSEMBLY_ELEMENT = "assembly";
+    public static final String DIFFERENCE_PROPERTY = "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<>();
+    private ArrayList<Pair<String, String>> blockConnections = new ArrayList<>();
+    private int maxId = 0;
+    private GraphDocument graphDocument;
+
+    private int lookupID(String i) {
+        try {
+            return Integer.parseInt(i);
+        } catch (NumberFormatException nfe) {
+            // ignore
+        }
+        Integer id = idCache.get(i);
+        if (id == null) {
+            id = maxId++;
+            idCache.put(i, id);
+        }
+        return id.intValue();
+    }
+
+    // <graphDocument>
+    private ElementHandler<GraphDocument, Object> topHandler = new ElementHandler<GraphDocument, Object>(TOP_ELEMENT) {
+
+        @Override
+        protected GraphDocument start() throws SAXException {
+            graphDocument = new GraphDocument();
+            return graphDocument;
+        }
+    };
+    // <group>
+    private ElementHandler<Group, Folder> groupHandler = new XMLParser.ElementHandler<Group, Folder>(GROUP_ELEMENT) {
+
+        @Override
+        protected Group start() throws SAXException {
+            final Group group = new Group(this.getParentObject());
+
+            String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY);
+            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 {
+        }
+    };
+    // <method>
+    private ElementHandler<InputMethod, Group> methodHandler = new XMLParser.ElementHandler<InputMethod, Group>(METHOD_ELEMENT) {
+
+        @Override
+        protected InputMethod start() throws SAXException {
+
+            InputMethod method = parseMethod(this, getParentObject());
+            getParentObject().setMethod(method);
+            return method;
+        }
+    };
+
+    private InputMethod parseMethod(XMLParser.ElementHandler<?,?> handler, Group group) throws SAXException {
+        String s = handler.readRequiredAttribute(METHOD_BCI_PROPERTY);
+        int bci = 0;
+        try {
+            bci = Integer.parseInt(s);
+        } catch (NumberFormatException e) {
+            throw new SAXException(e);
+        }
+        InputMethod method = new InputMethod(group, handler.readRequiredAttribute(METHOD_NAME_PROPERTY), handler.readRequiredAttribute(METHOD_SHORT_NAME_PROPERTY), bci);
+        return method;
+    }
+    // <bytecodes>
+    private HandoverElementHandler<InputMethod> bytecodesHandler = new XMLParser.HandoverElementHandler<InputMethod>(BYTECODES_ELEMENT, true) {
+
+        @Override
+        protected void end(String text) throws SAXException {
+            getParentObject().setBytecodes(text);
+        }
+    };
+    // <inlined>
+    private HandoverElementHandler<InputMethod> inlinedHandler = new XMLParser.HandoverElementHandler<>(INLINE_ELEMENT);
+    // <inlined><method>
+    private ElementHandler<InputMethod, InputMethod> inlinedMethodHandler = new XMLParser.ElementHandler<InputMethod, InputMethod>(METHOD_ELEMENT) {
+
+        @Override
+        protected InputMethod start() throws SAXException {
+            InputMethod method = parseMethod(this, getParentObject().getGroup());
+            getParentObject().addInlined(method);
+            return method;
+        }
+    };
+    // <graph>
+    private ElementHandler<InputGraph, Group> graphHandler = new XMLParser.ElementHandler<InputGraph, Group>(GRAPH_ELEMENT) {
+
+        @Override
+        protected InputGraph start() throws SAXException {
+            String name = readAttribute(GRAPH_NAME_PROPERTY);
+            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);
+                    }
+                }
+            }
+            return curGraph;
+        }
+
+        @Override
+        protected void end(String text) throws SAXException {
+            // 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<>(NODES_ELEMENT);
+    // <controlFlow>
+    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);
+            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<>(NODES_ELEMENT);
+    // <node>
+    private ElementHandler<InputBlock, InputBlock> blockNodeHandler = new ElementHandler<InputBlock, InputBlock>(NODE_ELEMENT) {
+
+        @Override
+        protected InputBlock start() throws SAXException {
+            String s = readRequiredAttribute(NODE_ID_PROPERTY);
+
+            int id = 0;
+            try {
+                id = lookupID(s);
+            } catch (NumberFormatException e) {
+                throw new SAXException(e);
+            }
+            getParentObject().addNode(id);
+            return getParentObject();
+        }
+    };
+    // <successors>
+    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);
+            blockConnections.add(new Pair<>(getParentObject().getName(), name));
+            return getParentObject();
+        }
+    };
+    // <node>
+    private ElementHandler<InputNode, InputGraph> nodeHandler = new ElementHandler<InputNode, InputGraph>(NODE_ELEMENT) {
+
+        @Override
+        protected InputNode start() throws SAXException {
+            String s = readRequiredAttribute(NODE_ID_PROPERTY);
+            int id = 0;
+            try {
+                id = lookupID(s);
+            } catch (NumberFormatException e) {
+                throw new SAXException(e);
+            }
+            InputNode node = new InputNode(id);
+            getParentObject().addNode(node);
+            return node;
+        }
+    };
+    // <removeNode>
+    private ElementHandler<InputNode, InputGraph> removeNodeHandler = new ElementHandler<InputNode, InputGraph>(REMOVE_NODE_ELEMENT) {
+
+        @Override
+        protected InputNode start() throws SAXException {
+            String s = readRequiredAttribute(NODE_ID_PROPERTY);
+            int id = 0;
+            try {
+                id = lookupID(s);
+            } catch (NumberFormatException e) {
+                throw new SAXException(e);
+            }
+            return getParentObject().removeNode(id);
+        }
+    };
+    // <graph>
+    private HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<>(EDGES_ELEMENT);
+
+    // Local class for edge elements
+    private class EdgeElementHandler extends ElementHandler<InputEdge, InputGraph> {
+
+        public EdgeElementHandler(String name) {
+            super(name);
+        }
+
+        @Override
+        protected InputEdge start() throws SAXException {
+            int fromIndex = 0;
+            int toIndex = 0;
+            int from = -1;
+            int to = -1;
+            String label = 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);
+
+                from = lookupID(readRequiredAttribute(FROM_PROPERTY));
+                to = lookupID(readRequiredAttribute(TO_PROPERTY));
+            } catch (NumberFormatException e) {
+                throw new SAXException(e);
+            }
+
+            InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label);
+            return start(conn);
+        }
+
+        protected InputEdge start(InputEdge conn) throws SAXException {
+            return conn;
+        }
+    }
+    // <edge>
+    private EdgeElementHandler edgeHandler = new EdgeElementHandler(EDGE_ELEMENT) {
+
+        @Override
+        protected InputEdge start(InputEdge conn) throws SAXException {
+            getParentObject().addEdge(conn);
+            return conn;
+        }
+    };
+    // <removeEdge>
+    private EdgeElementHandler removeEdgeHandler = new EdgeElementHandler(REMOVE_EDGE_ELEMENT) {
+
+        @Override
+        protected InputEdge start(InputEdge conn) throws SAXException {
+            getParentObject().removeEdge(conn);
+            return conn;
+        }
+    };
+    // <properties>
+    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 && getParentObject().getParent() instanceof GraphDocument) {
+                final Group group = getParentObject();
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        groupCallback.started(group);
+                    }
+                });
+            }
+        }
+    };
+    // <property>
+    private ElementHandler<String, Properties.Provider> propertyHandler = new XMLParser.ElementHandler<String, Properties.Provider>(PROPERTY_ELEMENT, true) {
+
+        @Override
+        public String start() throws SAXException {
+            return readRequiredAttribute(PROPERTY_NAME_PROPERTY);
+         }
+
+        @Override
+        public void end(String text) {
+            getParentObject().getProperties().setProperty(getObject(), text.trim());
+        }
+    };
+
+    public Parser() {
+        this(null);
+    }
+
+    public Parser(GroupCallback groupCallback) {
+
+        this.groupCallback = groupCallback;
+
+        // Initialize dependencies
+        xmlDocument.addChild(topHandler);
+        topHandler.addChild(groupHandler);
+
+        groupHandler.addChild(methodHandler);
+        groupHandler.addChild(graphHandler);
+        groupHandler.addChild(groupHandler);
+
+        methodHandler.addChild(inlinedHandler);
+        methodHandler.addChild(bytecodesHandler);
+
+        inlinedHandler.addChild(inlinedMethodHandler);
+        inlinedMethodHandler.addChild(bytecodesHandler);
+        inlinedMethodHandler.addChild(inlinedHandler);
+
+        graphHandler.addChild(nodesHandler);
+        graphHandler.addChild(edgesHandler);
+        graphHandler.addChild(controlFlowHandler);
+
+        controlFlowHandler.addChild(blockHandler);
+
+        blockHandler.addChild(successorsHandler);
+        successorsHandler.addChild(successorHandler);
+        blockHandler.addChild(blockNodesHandler);
+        blockNodesHandler.addChild(blockNodeHandler);
+
+        nodesHandler.addChild(nodeHandler);
+        nodesHandler.addChild(removeNodeHandler);
+        edgesHandler.addChild(edgeHandler);
+        edgesHandler.addChild(removeEdgeHandler);
+
+        methodHandler.addChild(propertiesHandler);
+        inlinedMethodHandler.addChild(propertiesHandler);
+        topHandler.addChild(propertiesHandler);
+        groupHandler.addChild(groupPropertiesHandler);
+        graphHandler.addChild(propertiesHandler);
+        nodeHandler.addChild(propertiesHandler);
+        propertiesHandler.addChild(propertyHandler);
+        groupPropertiesHandler.addChild(propertyHandler);
+    }
+
+    // Returns a new GraphDocument object deserialized from an XML input source.
+    public GraphDocument parse(InputSource source, XMLParser.ParseMonitor monitor) throws SAXException {
+        XMLReader reader = createReader();
+
+        reader.setContentHandler(new XMLParser(xmlDocument, monitor));
+        try {
+            reader.parse(source);
+        } catch (IOException ex) {
+            throw new SAXException(ex);
+        }
+
+        return graphDocument;
+    }
+
+    private XMLReader createReader() throws SAXException {
+        try {
+            SAXParserFactory pfactory = SAXParserFactory.newInstance();
+            pfactory.setValidating(false);
+            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);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,245 @@
+/*
+ * 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.serialization;
+
+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;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+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);
+
+        try {
+            export(xmlWriter, document);
+        } catch (IOException ex) {
+        }
+    }
+
+    private void export(XMLWriter xmlWriter, GraphDocument document) throws IOException {
+        xmlWriter.startTag(Parser.ROOT_ELEMENT);
+        xmlWriter.writeProperties(document.getProperties());
+        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();
+        xmlWriter.flush();
+    }
+
+    private void export(XMLWriter writer, Group g) throws IOException {
+        Properties attributes = new Properties();
+        attributes.setProperty("difference", Boolean.toString(true));
+        writer.startTag(Parser.GROUP_ELEMENT, attributes);
+        writer.writeProperties(g.getProperties());
+
+        boolean shouldExport = true;
+        if (in != null) {
+            char c = (char) in.read();
+            if (c != 'y') {
+                shouldExport = false;
+            }
+        }
+
+        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();
+    }
+
+    public void export(XMLWriter writer, InputGraph graph, InputGraph previous, boolean difference) throws IOException {
+
+        writer.startTag(Parser.GRAPH_ELEMENT);
+        writer.writeProperties(graph.getProperties());
+        writer.startTag(Parser.NODES_ELEMENT);
+
+        Set<InputNode> removed = new HashSet<>();
+        Set<InputNode> equal = new HashSet<>();
+
+        if (previous != null) {
+            for (InputNode n : previous.getNodes()) {
+                int id = n.getId();
+                InputNode n2 = graph.getNode(id);
+                if (n2 == null) {
+                    removed.add(n);
+                } else if (n.equals(n2)) {
+                    equal.add(n);
+                }
+            }
+        }
+
+        if (difference) {
+            for (InputNode n : removed) {
+                writer.simpleTag(Parser.REMOVE_NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId())));
+            }
+        }
+
+        for (InputNode n : graph.getNodes()) {
+            if (!difference || !equal.contains(n)) {
+                writer.startTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId())));
+                writer.writeProperties(n.getProperties());
+                writer.endTag();
+            }
+        }
+
+        writer.endTag();
+
+        writer.startTag(Parser.EDGES_ELEMENT);
+        Set<InputEdge> removedEdges = new HashSet<>();
+        Set<InputEdge> equalEdges = new HashSet<>();
+
+        if (previous != null) {
+            for (InputEdge e : previous.getEdges()) {
+                if (graph.getEdges().contains(e)) {
+                    equalEdges.add(e);
+                } else {
+                    removedEdges.add(e);
+                }
+            }
+        }
+
+        if (difference) {
+            for (InputEdge e : removedEdges) {
+                writer.simpleTag(Parser.REMOVE_EDGE_ELEMENT, createProperties(e));
+            }
+        }
+
+        for (InputEdge e : graph.getEdges()) {
+            if (!difference || !equalEdges.contains(e)) {
+                if (!equalEdges.contains(e)) {
+                    writer.simpleTag(Parser.EDGE_ELEMENT, createProperties(e));
+                }
+            }
+        }
+
+        writer.endTag();
+
+        writer.startTag(Parser.CONTROL_FLOW_ELEMENT);
+        for (InputBlock b : graph.getBlocks()) {
+            writer.startTag(Parser.BLOCK_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, b.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();
+            }
+
+            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() + ""));
+                }
+                writer.endTag();
+            }
+            
+            writer.endTag();
+        }
+
+        writer.endTag();
+        writer.endTag();
+    }
+
+    private void export(XMLWriter w, InputMethod method) throws IOException {
+
+        w.startTag(Parser.METHOD_ELEMENT, new Properties(Parser.METHOD_BCI_PROPERTY, method.getBci() + "", Parser.METHOD_NAME_PROPERTY, method.getName(), Parser.METHOD_SHORT_NAME_PROPERTY, method.getShortName()));
+
+        w.writeProperties(method.getProperties());
+
+        if (method.getInlined().size() > 0) {
+            w.startTag(Parser.INLINE_ELEMENT);
+            for (InputMethod m : method.getInlined()) {
+                export(w, m);
+            }
+            w.endTag();
+        }
+
+        w.startTag(Parser.BYTECODES_ELEMENT);
+
+        StringBuilder b = new StringBuilder();
+        b.append("<![CDATA[\n");
+        for (InputBytecode code : method.getBytecodes()) {
+            b.append(code.getBci());
+            b.append(" ");
+            b.append(code.getName());
+            b.append("\n");
+        }
+        
+        b.append("]]>");
+        w.write(b.toString());
+        w.endTag();
+        w.endTag();
+    }
+
+    private Properties createProperties(InputEdge edge) {
+        Properties p = new Properties();
+        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()));
+        return p;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,270 @@
+/*
+ * 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.serialization;
+
+import com.sun.hotspot.igv.data.Properties;
+import java.util.HashMap;
+import java.util.Stack;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+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;
+
+        public MissingAttributeException(String name) {
+            super("Missing attribute \"" + name + "\"");
+            this.name = name;
+        }
+
+        public String getAttributeName() {
+            return this.getMessage();
+        }
+    }
+
+    public static class HandoverElementHandler<P> extends ElementHandler<P, P> {
+
+        @Override
+        protected P start() throws SAXException {
+            return getParentObject();
+        }
+
+        public HandoverElementHandler(String name) {
+            super(name);
+        }
+
+        public HandoverElementHandler(String name, boolean needsText) {
+            super(name, needsText);
+        }
+    }
+
+    public static class TopElementHandler<P> extends ElementHandler<P, Object> {
+
+        public TopElementHandler() {
+            super(null);
+        }
+    }
+
+    public static class ElementHandler<T, P> {
+
+        private String name;
+        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 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.peek();
+        }
+
+        public P getParentObject() {
+            return parentObject.peek();
+        }
+
+        protected boolean needsText() {
+            return needsText;
+        }
+
+        public ElementHandler(String name, boolean needsText) {
+            this.hashtable = new HashMap<>();
+            this.name = name;
+            this.needsText = needsText;
+        }
+
+        public ParseMonitor getMonitor() {
+            return monitor;
+        }
+
+        public ElementHandler<?, ? super T> getChild(String name) {
+            return hashtable.get(name);
+        }
+
+        public void addChild(ElementHandler<?, ? super T> handler) {
+            assert handler != null;
+            hashtable.put(handler.getName(), handler);
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public T getObject() {
+            return object.size() == 0 ? null : object.peek();
+        }
+
+        public String readAttribute(String name) {
+            return attr.getValue(name);
+        }
+
+        public String readRequiredAttribute(String name) throws SAXException {
+            String s = readAttribute(name);
+            if (s == null) {
+                throw new MissingAttributeException(name);
+            }
+            return s;
+        }
+
+        public void processAttributesAsProperties(Properties p) {
+            int length = attr.getLength();
+            for (int i = 0; i < length; i++) {
+                String val = attr.getValue(i);
+                String localName = attr.getLocalName(i);
+                p.setProperty(val, localName);
+            }
+        }
+
+        public void startElement(ElementHandler<P, ?> parentElement, Attributes attr, ParseMonitor monitor) throws SAXException {
+            this.currentText = new StringBuilder();
+            this.attr = attr;
+            this.monitor = monitor;
+            this.parentElement.push(parentElement);
+            parentObject.push(parentElement.getObject());
+            object.push(start());
+        }
+
+        protected T start() throws SAXException {
+            return null;
+        }
+
+        protected void end(String text) throws SAXException {
+
+        }
+
+        public void endElement() throws SAXException {
+            end(currentText.toString());
+            object.pop();
+            parentElement.pop();
+            parentObject.pop();
+        }
+
+        protected void text(char[] c, int start, int length) {
+            assert currentText != null;
+            currentText.append(c, start, length);
+        }
+    }
+    private Stack<ElementHandler> stack;
+    private ParseMonitor monitor;
+
+    public XMLParser(TopElementHandler rootHandler, ParseMonitor monitor) {
+        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();
+
+        ElementHandler parent = stack.peek();
+        if (parent != null) {
+            ElementHandler child = parent.getChild(qName);
+            if (child != null) {
+                child.startElement(parent, atts, monitor);
+                stack.push(child);
+                return;
+            }
+        }
+
+        stack.push(null);
+    }
+
+    @Override
+    public void endElement(String uri, String localName, String qName) throws SAXException {
+        ElementHandler handler = stack.pop();
+        if (handler != null) {
+            handler.endElement();
+        }
+    }
+
+    @Override
+    public void characters(char[] ch, int start, int length) throws SAXException {
+
+        assert !stack.isEmpty();
+
+
+        ElementHandler top = stack.peek();
+        if (top != null && top.needsText()) {
+            top.text(ch, start, length);
+        }
+    }
+
+    @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 {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 1998, 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.  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.Properties;
+import com.sun.hotspot.igv.data.Property;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Stack;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class XMLWriter extends Writer {
+
+    private Writer inner;
+    private Stack<String> elementStack;
+
+    public XMLWriter(Writer inner) {
+        this.inner = inner;
+        elementStack = new Stack<>();
+    }
+
+    @Override
+    public void write(char[] arr) throws IOException {
+        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];
+            if (c == '>') {
+                inner.write("&gt;");
+            } else if (c == '<') {
+                inner.write("&lt;");
+            } else if (c == '&') {
+                inner.write("&amp;");
+            } else {
+                inner.write(c);
+            }
+        }
+    }
+
+    @Override
+    public void flush() throws IOException {
+        inner.flush();
+    }
+
+    @Override
+    public void close() throws IOException {
+        inner.close();
+    }
+
+    public void endTag() throws IOException {
+        inner.write("</" + elementStack.pop() + ">\n");
+    }
+
+    public void startTag(String name) throws IOException {
+        inner.write("<" + name + ">\n");
+        elementStack.push(name);
+    }
+
+    public void simpleTag(String name) throws IOException {
+        inner.write("<" + name + "/>\n");
+    }
+
+    public void startTag(String name, Properties attributes) throws IOException {
+        inner.write("<" + name);
+        elementStack.push(name);
+
+        for (Property p : attributes) {
+            inner.write(" " + p.getName() + "=\"");
+            write(p.getValue().toCharArray());
+            inner.write("\"");
+        }
+
+        inner.write(">\n");
+    }
+
+    public void simpleTag(String name, Properties attributes) throws IOException {
+        inner.write("<" + name);
+
+        for (Property p : attributes) {
+            inner.write(" " + p.getName() + "=\"");
+            write(p.getValue().toCharArray());
+            inner.write("\"");
+        }
+
+        inner.write("/>\n");
+    }
+
+    public void writeProperties(Properties props) throws IOException {
+        if (props.iterator().hasNext() == false) {
+            return;
+        }
+
+        startTag(Parser.PROPERTIES_ELEMENT);
+
+        for (Property p : props) {
+            startTag(Parser.PROPERTY_ELEMENT, new Properties(Parser.PROPERTY_NAME_PROPERTY, p.getName()));
+            this.write(p.getValue().toCharArray());
+            endTag();
+        }
+
+        endTag();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/graphdocument.xsd	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,146 @@
+<?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:element name="graph" type="graphType" minOccurs="0" maxOccurs="unbounded" />
+        </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="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>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/services/GraphViewer.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,35 @@
+/*
+ * 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.InputGraph;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface GraphViewer {
+
+    public void view(InputGraph graph);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/services/GroupCallback.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,36 @@
+/*
+ * 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.data.services;
+
+import com.sun.hotspot.igv.data.Group;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface GroupCallback {
+
+    public void started(Group g);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/services/InputGraphProvider.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,40 @@
+/*
+ * 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.data.services;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.InputNode;
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface InputGraphProvider {
+
+    InputGraph getGraph();
+
+    void setSelectedNodes(Set<InputNode> nodes);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/services/Scheduler.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,38 @@
+/*
+ * 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.data.services;
+
+import com.sun.hotspot.igv.data.InputBlock;
+import com.sun.hotspot.igv.data.InputGraph;
+import java.util.Collection;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface Scheduler {
+
+    public Collection<InputBlock> schedule(InputGraph graph);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ChangedEventTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,95 @@
+/*
+ * 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;
+
+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]);
+
+    }
+
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ControllableChangedListenerTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,93 @@
+/*
+ * 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;
+
+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]);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/GroupTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+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)));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputGraphTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,211 @@
+/*
+ * 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;
+
+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());
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputMethodTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.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());
+    }
+
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PairTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,98 @@
+/*
+ * 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.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));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertiesTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,401 @@
+/*
+ * 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.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/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertyTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,116 @@
+/*
+ * 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.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());
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/SourceTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.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)));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/Util.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,126 @@
+/*
+ * 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.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/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/serialization/ParserTest.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,223 @@
+/*
+ * 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.data.serialization;
+
+import com.sun.hotspot.igv.data.*;
+import java.io.CharArrayWriter;
+import java.io.StringReader;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.*;
+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) {
+        
+        StringReader sr = new StringReader(xmlString);
+        InputSource is = new InputSource(sr);
+
+        try {
+            Parser parser = new Parser();
+            final GraphDocument parsedDocument = parser.parse(is, null);
+            Util.assertGraphDocumentEquals(document, parsedDocument);
+        } catch (SAXException ex) {
+            fail(ex.toString());
+        }
+    }
+
+    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>");
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Difference/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.difference" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.difference.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Difference/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.difference
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/difference/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Difference/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.difference-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Difference/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=1657ecfe
+build.xml.script.CRC32=03909051
+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=1657ecfe
+nbproject/build-impl.xml.script.CRC32=2208e770
+nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Difference/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Difference/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Difference/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,31 @@
+<?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.difference</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>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>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Difference/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Difference/src/com/sun/hotspot/igv/difference/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Difference
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 1998, 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.  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.difference;
+
+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;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Difference {
+
+    public static final String PROPERTY_STATE = "state";
+    public static final String VALUE_NEW = "new";
+    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 MAIN_PROPERTY = "name";
+    public static final double LIMIT = 100.0;
+    public static final String[] IGNORE_PROPERTIES = new String[]{"idx", "debug_idx"};
+
+    public static InputGraph createDiffGraph(InputGraph a, InputGraph b) {
+        if (a.getGroup() == b.getGroup()) {
+            return createDiffSameGroup(a, b);
+        } else {
+            return createDiff(a, b);
+        }
+    }
+
+    private static InputGraph createDiffSameGroup(InputGraph a, InputGraph b) {
+        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<NodePair> pairs = new HashSet<>();
+
+        for (InputNode n : a.getNodes()) {
+            Integer key = n.getId();
+
+
+            if (keyMapB.containsKey(key)) {
+                InputNode nB = keyMapB.get(key);
+                pairs.add(new NodePair(n, nB));
+            }
+        }
+
+        return createDiff(a, b, pairs);
+    }
+
+    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());
+        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(a.getName() + ", " + b.getName());
+        g.addElement(graph);
+
+        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);
+        }
+
+        // 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.getRight();
+            assert nodesB.contains(nB);
+
+            nodesA.remove(n);
+            nodesB.remove(nB);
+            InputNode n2 = new InputNode(n);
+            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);
+            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);
+
+            // 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);
+            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<>();
+
+        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 fromIndex = e.getFromIndex();
+            char toIndex = e.getToIndex();
+
+            InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId());
+            if (!newEdges.contains(newEdge)) {
+                markAsDeleted(newEdge);
+                newEdges.add(newEdge);
+                graph.addEdge(newEdge);
+            }
+        }
+
+        for (InputEdge e : edgesB) {
+            int from = e.getFrom();
+            int to = e.getTo();
+            InputNode nodeFrom = inputNodeMap.get(b.getNode(from));
+            InputNode nodeTo = inputNodeMap.get(b.getNode(to));
+            char fromIndex = e.getFromIndex();
+            char toIndex = e.getToIndex();
+
+            InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId());
+            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);
+            }
+        }
+
+        return graph;
+    }
+
+    private static class NodePair extends Pair<InputNode, InputNode> {
+
+
+        public NodePair(InputNode n1, InputNode n2) {
+            super(n1, n2);
+        }
+
+        public double getValue() {
+
+            double result = 0.0;
+            for (Property p : getLeft().getProperties()) {
+                double faktor = 1.0;
+                for (String forbidden : IGNORE_PROPERTIES) {
+                    if (p.getName().equals(forbidden)) {
+                        faktor = 0.1;
+                        break;
+                    }
+                }
+                String p2 = getRight().getProperties().get(p.getName());
+                result += evaluate(p.getValue(), p2) * faktor;
+            }
+
+            return result;
+        }
+
+        private double evaluate(String p, String p2) {
+            if (p2 == null) {
+                return 1.0;
+            }
+            if (p.equals(p2)) {
+                return 0.0;
+            } else {
+                return (double) (Math.abs(p.length() - p2.length())) / p.length() + 0.5;
+            }
+        }
+    }
+
+    private static InputGraph createDiff(InputGraph a, InputGraph b) {
+
+        Set<InputNode> matched = new HashSet<>();
+
+        Set<NodePair> pairs = new HashSet<>();
+        for (InputNode n : a.getNodes()) {
+            String s = n.getProperties().get(MAIN_PROPERTY);
+            if (s == null) {
+                s = "";
+            }
+            for (InputNode n2 : b.getNodes()) {
+                String s2 = n2.getProperties().get(MAIN_PROPERTY);
+                if (s2 == null) {
+                    s2 = "";
+                }
+
+                if (s.equals(s2)) {
+                    NodePair p = new NodePair(n, n2);
+                    pairs.add(p);
+                }
+            }
+        }
+
+        Set<NodePair> selectedPairs = new HashSet<>();
+        while (pairs.size() > 0) {
+
+            double min = Double.MAX_VALUE;
+            NodePair minPair = null;
+            for (NodePair p : pairs) {
+                double cur = p.getValue();
+                if (cur < min) {
+                    minPair = p;
+                    min = cur;
+                }
+            }
+
+            if (min > LIMIT) {
+                break;
+            } else {
+                selectedPairs.add(minPair);
+
+                Set<NodePair> toRemove = new HashSet<>();
+                for (NodePair p : pairs) {
+                    if (p.getLeft() == minPair.getLeft() || p.getRight() == minPair.getRight()) {
+                        toRemove.add(p);
+                    }
+                }
+                pairs.removeAll(toRemove);
+            }
+        }
+
+        return createDiff(a, b, selectedPairs);
+    }
+
+    private static void markAsNew(InputEdge e) {
+        e.setState(InputEdge.State.NEW);
+    }
+
+    private static void markAsDeleted(InputEdge e) {
+        e.setState(InputEdge.State.DELETED);
+
+    }
+
+    private static void markAsSame(InputEdge e) {
+        e.setState(InputEdge.State.SAME);
+    }
+
+    private static void markAsChanged(InputNode n, InputNode firstNode, InputNode otherNode) {
+
+        boolean difference = false;
+        for (Property p : otherNode.getProperties()) {
+            String s = firstNode.getProperties().get(p.getName());
+            if (!p.getValue().equals(s)) {
+                difference = true;
+                n.getProperties().setProperty(OLD_PREFIX + p.getName(), p.getValue());
+            }
+        }
+
+        for (Property p : firstNode.getProperties()) {
+            String s = otherNode.getProperties().get(p.getName());
+            if (s == null && p.getValue().length() > 0) {
+                difference = true;
+                n.getProperties().setProperty(OLD_PREFIX + p.getName(), "");
+            }
+        }
+
+        if (difference) {
+            n.getProperties().setProperty(PROPERTY_STATE, VALUE_CHANGED);
+        } else {
+            n.getProperties().setProperty(PROPERTY_STATE, VALUE_SAME);
+        }
+    }
+
+    private static void markAsDeleted(InputNode n) {
+        n.getProperties().setProperty(PROPERTY_STATE, VALUE_DELETED);
+    }
+
+    private static void markAsNew(InputNode n) {
+        n.getProperties().setProperty(PROPERTY_STATE, VALUE_NEW);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Draw2DLibrary/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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="org.eclipse.draw2d" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project org.eclipse.draw2d.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Draw2DLibrary/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: org.eclipse.draw2d
+OpenIDE-Module-Localizing-Bundle: org/eclipse/draw2d/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Draw2DLibrary/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="org.eclipse.draw2d-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/visualizer/Draw2DLibrary/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=36988202
+build.xml.script.CRC32=0429cbcb
+build.xml.stylesheet.CRC32=a56c6a5b@2.47.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=36988202
+nbproject/build-impl.xml.script.CRC32=92856d71
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Draw2DLibrary/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,204 @@
+cluster.path=\
+    ${nbplatform.active.dir}/ide:\
+    ${nbplatform.active.dir}/platform
+disabled.modules=\
+    com.jcraft.jsch,\
+    com.jcraft.jzlib,\
+    org.apache.commons.codec,\
+    org.apache.commons.httpclient,\
+    org.apache.commons.io,\
+    org.apache.commons.lang,\
+    org.apache.commons.logging,\
+    org.apache.ws.commons.util,\
+    org.apache.xml.resolver,\
+    org.apache.xmlrpc,\
+    org.eclipse.core.contenttype,\
+    org.eclipse.core.jobs,\
+    org.eclipse.core.net,\
+    org.eclipse.core.runtime,\
+    org.eclipse.core.runtime.compatibility.auth,\
+    org.eclipse.equinox.app,\
+    org.eclipse.equinox.common,\
+    org.eclipse.equinox.preferences,\
+    org.eclipse.equinox.registry,\
+    org.eclipse.equinox.security,\
+    org.eclipse.jgit,\
+    org.eclipse.mylyn.bugzilla.core,\
+    org.eclipse.mylyn.commons.core,\
+    org.eclipse.mylyn.commons.net,\
+    org.eclipse.mylyn.commons.xmlrpc,\
+    org.eclipse.mylyn.tasks.core,\
+    org.mozilla.rhino.patched,\
+    org.netbeans.api.debugger,\
+    org.netbeans.api.java.classpath,\
+    org.netbeans.api.xml,\
+    org.netbeans.core.browser,\
+    org.netbeans.core.execution,\
+    org.netbeans.core.ide,\
+    org.netbeans.core.io.ui,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.nativeaccess,\
+    org.netbeans.core.osgi,\
+    org.netbeans.lib.cvsclient,\
+    org.netbeans.lib.terminalemulator,\
+    org.netbeans.libs.antlr3.runtime,\
+    org.netbeans.libs.bytelist,\
+    org.netbeans.libs.commons_net,\
+    org.netbeans.libs.freemarker,\
+    org.netbeans.libs.git,\
+    org.netbeans.libs.ini4j,\
+    org.netbeans.libs.jaxb,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.junit4,\
+    org.netbeans.libs.jvyamlb,\
+    org.netbeans.libs.lucene,\
+    org.netbeans.libs.smack,\
+    org.netbeans.libs.svnClientAdapter,\
+    org.netbeans.libs.svnClientAdapter.javahl,\
+    org.netbeans.libs.svnClientAdapter.svnkit,\
+    org.netbeans.libs.swingx,\
+    org.netbeans.libs.xerces,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.bugtracking,\
+    org.netbeans.modules.bugtracking.bridge,\
+    org.netbeans.modules.bugzilla,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.csl.api,\
+    org.netbeans.modules.css.editor,\
+    org.netbeans.modules.css.lib,\
+    org.netbeans.modules.css.visual,\
+    org.netbeans.modules.db,\
+    org.netbeans.modules.db.core,\
+    org.netbeans.modules.db.dataview,\
+    org.netbeans.modules.db.drivers,\
+    org.netbeans.modules.db.kit,\
+    org.netbeans.modules.db.metadata.model,\
+    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.derby,\
+    org.netbeans.modules.dlight.nativeexecution,\
+    org.netbeans.modules.dlight.terminal,\
+    org.netbeans.modules.editor.bookmarks,\
+    org.netbeans.modules.editor.bracesmatching,\
+    org.netbeans.modules.editor.codetemplates,\
+    org.netbeans.modules.editor.completion,\
+    org.netbeans.modules.editor.guards,\
+    org.netbeans.modules.editor.indent.project,\
+    org.netbeans.modules.editor.kit,\
+    org.netbeans.modules.editor.macros,\
+    org.netbeans.modules.editor.structure,\
+    org.netbeans.modules.extbrowser,\
+    org.netbeans.modules.extexecution,\
+    org.netbeans.modules.extexecution.destroy,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.git,\
+    org.netbeans.modules.glassfish.common,\
+    org.netbeans.modules.gototest,\
+    org.netbeans.modules.gsf.codecoverage,\
+    org.netbeans.modules.gsf.testrunner,\
+    org.netbeans.modules.html,\
+    org.netbeans.modules.html.editor,\
+    org.netbeans.modules.html.editor.lib,\
+    org.netbeans.modules.html.lexer,\
+    org.netbeans.modules.html.parser,\
+    org.netbeans.modules.html.validation,\
+    org.netbeans.modules.httpserver,\
+    org.netbeans.modules.hudson,\
+    org.netbeans.modules.hudson.git,\
+    org.netbeans.modules.hudson.mercurial,\
+    org.netbeans.modules.hudson.subversion,\
+    org.netbeans.modules.hudson.tasklist,\
+    org.netbeans.modules.ide.kit,\
+    org.netbeans.modules.image,\
+    org.netbeans.modules.javascript.editing,\
+    org.netbeans.modules.javascript.hints,\
+    org.netbeans.modules.javascript.kit,\
+    org.netbeans.modules.javascript.refactoring,\
+    org.netbeans.modules.jellytools.ide,\
+    org.netbeans.modules.jumpto,\
+    org.netbeans.modules.keyring.impl,\
+    org.netbeans.modules.languages,\
+    org.netbeans.modules.languages.diff,\
+    org.netbeans.modules.languages.manifest,\
+    org.netbeans.modules.languages.yaml,\
+    org.netbeans.modules.lexer.nbbridge,\
+    org.netbeans.modules.localhistory,\
+    org.netbeans.modules.mercurial,\
+    org.netbeans.modules.netbinox,\
+    org.netbeans.modules.parsing.api,\
+    org.netbeans.modules.parsing.lucene,\
+    org.netbeans.modules.print.editor,\
+    org.netbeans.modules.project.ant,\
+    org.netbeans.modules.project.libraries,\
+    org.netbeans.modules.projectui,\
+    org.netbeans.modules.projectui.buildmenu,\
+    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.server,\
+    org.netbeans.modules.servletapi,\
+    org.netbeans.modules.spellchecker,\
+    org.netbeans.modules.spellchecker.apimodule,\
+    org.netbeans.modules.spellchecker.bindings.htmlxml,\
+    org.netbeans.modules.spellchecker.bindings.properties,\
+    org.netbeans.modules.spellchecker.dictionary_en,\
+    org.netbeans.modules.spellchecker.kit,\
+    org.netbeans.modules.spi.actions,\
+    org.netbeans.modules.subversion,\
+    org.netbeans.modules.swing.validation,\
+    org.netbeans.modules.target.iterator,\
+    org.netbeans.modules.tasklist.kit,\
+    org.netbeans.modules.tasklist.projectint,\
+    org.netbeans.modules.tasklist.todo,\
+    org.netbeans.modules.tasklist.ui,\
+    org.netbeans.modules.terminal,\
+    org.netbeans.modules.usersguide,\
+    org.netbeans.modules.utilities,\
+    org.netbeans.modules.utilities.project,\
+    org.netbeans.modules.versioning,\
+    org.netbeans.modules.versioning.indexingbridge,\
+    org.netbeans.modules.versioning.system.cvss.installer,\
+    org.netbeans.modules.versioning.util,\
+    org.netbeans.modules.web.client.tools.api,\
+    org.netbeans.modules.web.common,\
+    org.netbeans.modules.web.indent,\
+    org.netbeans.modules.xml,\
+    org.netbeans.modules.xml.axi,\
+    org.netbeans.modules.xml.catalog,\
+    org.netbeans.modules.xml.core,\
+    org.netbeans.modules.xml.jaxb.api,\
+    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.execution,\
+    org.openide.options,\
+    org.openide.util.enumerations
+## 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,\
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Draw2DLibrary/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+is.autoload=true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Draw2DLibrary/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,25 @@
+<?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>org.eclipse.draw2d</code-name-base>
+            <suite-component/>
+            <module-dependencies/>
+            <public-packages>
+                <package>org.eclipse.draw2d</package>
+                <package>org.eclipse.draw2d.geometry</package>
+                <package>org.eclipse.draw2d.graph</package>
+                <package>org.eclipse.draw2d.internal</package>
+                <package>org.eclipse.draw2d.internal.graph</package>
+                <package>org.eclipse.draw2d.parts</package>
+                <package>org.eclipse.draw2d.text</package>
+                <package>org.eclipse.draw2d.widgets</package>
+            </public-packages>
+            <class-path-extension>
+                <runtime-relative-path>ext/org.eclipse.draw2d_3.1.0.jar</runtime-relative-path>
+                <binary-origin>release/modules/ext/org.eclipse.draw2d_3.1.0.jar</binary-origin>
+            </class-path-extension>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Draw2DLibrary/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
Binary file visualizer/Draw2DLibrary/release/modules/ext/org.eclipse.draw2d_3.1.0.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Draw2DLibrary/src/org/eclipse/draw2d/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Draw2DLibrary
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.oracle.graal.visualizer.editor" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.oracle.graal.visualizer.editor.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.oracle.graal.visualizer.editor
+OpenIDE-Module-Layer: com/oracle/graal/visualizer/editor/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/editor/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.oracle.graal.visualizer.editor-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/visualizer/Editor/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=5dcda8e3
+build.xml.script.CRC32=98c4f3b3
+build.xml.stylesheet.CRC32=a56c6a5b@2.47.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=5dcda8e3
+nbproject/build-impl.xml.script.CRC32=6243c7e2
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,136 @@
+<?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.oracle.graal.visualizer.editor</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.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>
+                <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.spi.quicksearch</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.12.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.24.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>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.23.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.53.2</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.loaders</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.32.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.19.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.11.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.48.1</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages>
+                <package>com.oracle.graal.visualizer.editor</package>
+                <package>com.oracle.graal.visualizer.editor.actions</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/META-INF/services/com.sun.hotspot.igv.data.services.GraphViewer	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+com.oracle.graal.visualizer.editor.GraphViewerImplementation
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,3 @@
+OpenIDE-Module-Name=Editor
+CTL_EditorTopComponent=Compilation
+HINT_EditorTopComponent=Shows the snapshots of a single compilation.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/CompilationViewer.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,43 @@
+/*
+ * 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.oracle.graal.visualizer.editor;
+
+import com.sun.hotspot.igv.graph.Figure;
+import java.awt.Component;
+import java.awt.Graphics2D;
+import java.util.Collection;
+import org.openide.awt.UndoRedo;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface CompilationViewer {
+
+    public Lookup getLookup();
+
+    public Component getComponent();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/CompilationViewerFactory.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.editor;
+
+import com.sun.hotspot.igv.data.InputGraph;
+
+public interface CompilationViewerFactory {
+    CompilationViewer createViewer(InputGraph firstGraph, InputGraph secondGraph);
+    String getName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/DiagramViewModel.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 1998, 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.  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.oracle.graal.visualizer.editor;
+
+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.graph.Figure;
+import com.sun.hotspot.igv.settings.Settings;
+import java.util.*;
+
+public class DiagramViewModel {
+
+    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> diagramChangedEvent;
+    private ChangedEvent<DiagramViewModel> viewChangedEvent;
+    private ChangedEvent<DiagramViewModel> hiddenNodesChangedEvent;
+    private ChangedEvent<DiagramViewModel> viewPropertiesChangedEvent;
+    private boolean showNodeHull;
+    private final InputGraph secondGraph;
+    private final InputGraph firstGraph;
+    private ChangedListener<FilterChain> filterChainChangedListener = new ChangedListener<FilterChain>() {
+
+        @Override
+        public void changed(FilterChain source) {
+            diagramChanged();
+        }
+    };
+
+    public boolean getShowNodeHull() {
+        return showNodeHull;
+    }
+
+    public void setShowNodeHull(boolean b) {
+        showNodeHull = b;
+        viewPropertiesChangedEvent.fire();
+    }
+
+    public DiagramViewModel(InputGraph firstGraph, InputGraph secondGraph, Group g, FilterChain filterChain, FilterChain sequenceFilterChain) {
+
+        this.firstGraph = firstGraph;
+        this.secondGraph = secondGraph;
+        this.showNodeHull = true;
+        assert filterChain != null;
+        this.filterChain = filterChain;
+        assert sequenceFilterChain != null;
+        this.sequenceFilterChain = sequenceFilterChain;
+        hiddenNodes = new HashSet<>();
+        onScreenNodes = new HashSet<>();
+        selectedNodes = new HashSet<>();
+        diagramChangedEvent = new ChangedEvent<>(this);
+        viewChangedEvent = new ChangedEvent<>(this);
+        hiddenNodesChangedEvent = new ChangedEvent<>(this);
+        viewPropertiesChangedEvent = new ChangedEvent<>(this);
+
+        filterChain.getChangedEvent().addListener(filterChainChangedListener);
+        sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener);
+    }
+
+    public ChangedEvent<DiagramViewModel> getDiagramChangedEvent() {
+        return diagramChangedEvent;
+    }
+
+    public ChangedEvent<DiagramViewModel> getViewChangedEvent() {
+        return viewChangedEvent;
+    }
+
+    public ChangedEvent<DiagramViewModel> getHiddenNodesChangedEvent() {
+        return hiddenNodesChangedEvent;
+    }
+
+    public ChangedEvent<DiagramViewModel> getViewPropertiesChangedEvent() {
+        return viewPropertiesChangedEvent;
+    }
+
+    public Set<Integer> getSelectedNodes() {
+        return selectedNodes;
+    }
+
+    public Set<Integer> getHiddenNodes() {
+        return hiddenNodes;
+    }
+
+    public Set<Integer> getOnScreenNodes() {
+        return onScreenNodes;
+    }
+
+    public void setSelectedNodes(Set<Integer> nodes) {
+        this.selectedNodes = nodes;
+       /* List<Color> colors = new ArrayList<>();
+        for (int i = 0; i < group.getGraphs().size(); ++i) {
+            colors.add(Color.black);
+        }
+        if (nodes.size() >= 1) {
+            for (Integer id : nodes) {
+                if (id < 0) {
+                    id = -id;
+                }
+                InputNode last = null;
+                int index = 0;
+                for (InputGraph g : group.getGraphs()) {
+                    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 (curColor == Color.black) {
+                                    curColor = Color.white;
+                                }
+                            } else {
+                                if (curColor != Color.green) {
+                                    curColor = Color.orange;
+                                }
+                            }
+                        }
+                    }
+                    last = cur;
+                    colors.set(index, curColor);
+                    index++;
+                }
+            }
+        }
+        compilationViewModel.setColors(colors);*/
+        // TODO: Add colorization.
+        viewChangedEvent.fire();
+    }
+
+    public void showNot(final Set<Integer> nodes) {
+        System.out.println("Shownot called with " + 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;
+        hiddenNodesChangedEvent.fire();
+    }
+
+    public void setOnScreenNodes(Set<Integer> onScreenNodes) {
+        this.onScreenNodes = onScreenNodes;
+        viewChangedEvent.fire();
+    }
+
+    public FilterChain getSequenceFilterChain() {
+        return filterChain;
+    }
+
+    public void setSequenceFilterChain(FilterChain chain) {
+        assert chain != null : "sequenceFilterChain must never be null";
+        sequenceFilterChain.getChangedEvent().removeListener(filterChainChangedListener);
+        sequenceFilterChain = chain;
+        sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener);
+        diagramChanged();
+    }
+
+    private void diagramChanged() {
+        // clear diagram
+        diagram = null;
+        getDiagramChangedEvent().fire();
+
+    }
+
+    public FilterChain getFilterChain() {
+        return filterChain;
+    }
+
+    public void setFilterChain(FilterChain chain) {
+        assert chain != null : "filterChain must never be null";
+        filterChain.getChangedEvent().removeListener(filterChainChangedListener);
+        filterChain = chain;
+        filterChain.getChangedEvent().addListener(filterChainChangedListener);
+        diagramChanged();
+    }
+
+    private static List<String> calculateStringList(Group g) {
+        List<String> result = new ArrayList<>();
+        for (InputGraph graph : g.getGraphs()) {
+            result.add(graph.getName());
+        }
+        return result;
+    }
+
+    public InputGraph getFirstGraph() {
+        return firstGraph;
+    }
+
+    public InputGraph getSecondGraph() {
+        return secondGraph;
+    }
+
+    public Diagram getDiagramToView() {
+
+        if (diagram == null) {
+            diagram = Diagram.createDiagram(getGraphToView(), Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT));
+            getFilterChain().apply(diagram, getSequenceFilterChain());
+            if (getFirstGraph() != getSecondGraph()) {
+                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 (inputGraph == null) {
+            if (getFirstGraph() != getSecondGraph()) {
+                inputGraph = Difference.createDiffGraph(getFirstGraph(), getSecondGraph());
+            } else {
+                inputGraph = getFirstGraph();
+            }
+        }
+
+        return inputGraph;
+    }
+
+    void setSelectedFigures(List<Figure> list) {
+        Set<Integer> newSelectedNodes = new HashSet<>();
+        for (Figure f : list) {
+            newSelectedNodes.addAll(f.getSource().getSourceNodesAsSet());
+        }
+        this.setSelectedNodes(newSelectedNodes);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/EditorTopComponent.form	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <NonVisualComponents>
+    <Component class="javax.swing.JCheckBox" name="jCheckBox1">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="jCheckBox1"/>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
+            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
+          </Border>
+        </Property>
+        <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+          <Insets value="[0, 0, 0, 0]"/>
+        </Property>
+      </Properties>
+    </Component>
+  </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"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
+  </AuxValues>
+
+  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
+</Form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/EditorTopComponent.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.editor;
+
+import com.oracle.graal.visualizer.util.LookupUtils;
+import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.data.Group;
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.util.RangeSliderModel;
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.*;
+import java.util.prefs.Preferences;
+import javax.swing.*;
+import org.openide.awt.Toolbar;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+import org.openide.util.NbPreferences;
+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.Lookups;
+import org.openide.util.lookup.ProxyLookup;
+import org.openide.windows.Mode;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
+
+public final class EditorTopComponent extends TopComponent {
+
+    private InstanceContent content;
+    private static final String PREFERRED_ID = "EditorTopComponent";
+    private RangeSliderModel rangeSliderModel;
+    private CompilationViewer activeViewer;
+    private CompilationViewerFactory activeFactory;
+    private Group group;
+    private final JToolBar viewerToolBar;
+    private final JPanel viewerPanel;
+    private final CardLayout viewerPanelCardLayout;
+    private final Map<String, CompilationViewer> createdComponents = new HashMap<>();
+    private final Lookup proxyLookup;
+    private Lookup currentLookup = Lookups.fixed();
+    private final Lookup.Provider currentViewLookupProvider = new Lookup.Provider() {
+
+        @Override
+        public Lookup getLookup() {
+            return currentLookup;
+        }
+    };
+    private static final String PREFERENCE_FACTORY = "factory";
+
+    public static Preferences getPreferences() {
+        return NbPreferences.forModule(EditorTopComponent.class);
+    }
+
+    private InputGraph getFirstGraph() {
+        return group.getGraphs().get(getModel().getFirstPosition());
+    }
+
+    private InputGraph getSecondGraph() {
+        return group.getGraphs().get(getModel().getSecondPosition());
+    }
+
+    private void updateDisplayName() {
+        int first = getModel().getFirstPosition();
+        int second = getModel().getSecondPosition();
+        if (first == second) {
+            setDisplayName(getModel().getPositions().get(first));
+        } else {
+            setDisplayName(String.format("%s: %s - %s", activeFactory.getName(), getModel().getPositions().get(first), getModel().getPositions().get(second)));
+        }
+    }
+
+    private void activateFactory(CompilationViewerFactory factory) {
+        this.activeFactory = factory;
+        getPreferences().put(PREFERENCE_FACTORY, activeFactory.getName());
+        updateView();
+    }
+
+    public EditorTopComponent(InputGraph graph) {
+        setName(NbBundle.getMessage(EditorTopComponent.class, "CTL_EditorTopComponent"));
+        setToolTipText(NbBundle.getMessage(EditorTopComponent.class, "HINT_EditorTopComponent"));
+
+        initComponents();
+
+        Toolbar toolBar = new Toolbar();
+        this.add(BorderLayout.NORTH, toolBar);
+
+        this.group = graph.getGroup();
+        rangeSliderModel = new RangeSliderModel(calculateStringList(group));
+        content = new InstanceContent();
+        content.add(rangeSliderModel);
+        int graphPos = group.getGraphs().indexOf(graph);
+        rangeSliderModel.setPositions(graphPos, graphPos);
+
+        Collection<? extends CompilationViewerFactory> factories = Lookup.getDefault().lookupAll(CompilationViewerFactory.class);
+        proxyLookup = Lookups.proxy(currentViewLookupProvider);
+        this.associateLookup(new ProxyLookup(new Lookup[]{proxyLookup, new AbstractLookup(content)}));
+
+        rangeSliderModel.getChangedEvent().addListener(rangeSliderListener);
+
+        ButtonGroup factoryButtonGroup = new ButtonGroup();
+        for (CompilationViewerFactory factory : factories) {
+            AbstractButton button = createFactoryChangeButton(factory);
+            factoryButtonGroup.add(button);
+            toolBar.add(button);
+        }
+        toolBar.addSeparator();
+
+        viewerToolBar = new JToolBar();
+        viewerToolBar.setFloatable(false);
+        toolBar.add(viewerToolBar);
+        toolBar.add(Box.createHorizontalGlue());
+
+        Action action = Utilities.actionsForPath("QuickSearchShadow").get(0);
+        Component quicksearch = ((Presenter.Toolbar) action).getToolbarPresenter();
+        quicksearch.setMinimumSize(quicksearch.getPreferredSize()); // necessary for GTK LAF
+        toolBar.add(quicksearch);
+
+        viewerPanel = new JPanel();
+        viewerPanelCardLayout = new CardLayout();
+        viewerPanel.setLayout(viewerPanelCardLayout);
+        this.add(viewerPanel, BorderLayout.CENTER);
+
+        if (factories.size() > 0) {
+            String activeFactoryName = getPreferences().get(PREFERENCE_FACTORY, factories.iterator().next().getName());
+            Enumeration<AbstractButton> buttons = factoryButtonGroup.getElements();
+            for (CompilationViewerFactory factory : factories) {
+                JToggleButton curButton = (JToggleButton) buttons.nextElement();
+                if (factory.getName().equals(activeFactoryName)) {
+                    activeFactory = factory;
+                    curButton.setSelected(true);
+                }
+            }
+        }
+        updateView();
+    }
+
+    private static List<String> calculateStringList(Group g) {
+        List<String> result = new ArrayList<>();
+        for (InputGraph graph : g.getGraphs()) {
+            result.add(graph.getName());
+        }
+        return result;
+    }
+
+    private RangeSliderModel getModel() {
+        return rangeSliderModel;
+    }
+
+    public static EditorTopComponent getActive() {
+        Set<? extends Mode> modes = WindowManager.getDefault().getModes();
+        for (Mode m : modes) {
+            TopComponent tc = m.getSelectedTopComponent();
+            if (tc instanceof EditorTopComponent) {
+                return (EditorTopComponent) tc;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jCheckBox1 = new javax.swing.JCheckBox();
+
+        org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, "jCheckBox1");
+        jCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
+        jCheckBox1.setMargin(new java.awt.Insets(0, 0, 0, 0));
+
+        setLayout(new java.awt.BorderLayout());
+    }// </editor-fold>//GEN-END:initComponents
+    // 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;
+    }
+
+    @Override
+    public void componentOpened() {
+    }
+
+    @Override
+    public void componentClosed() {
+    }
+
+    @Override
+    protected String preferredID() {
+        return PREFERRED_ID;
+    }
+    private ChangedListener<RangeSliderModel> rangeSliderListener = new ChangedListener<RangeSliderModel>() {
+
+        @Override
+        public void changed(RangeSliderModel source) {
+            SwingUtilities.invokeLater(new Runnable() {
+
+                @Override
+                public void run() {
+                    updateView();
+                }
+            });
+        }
+    };
+
+    private void updateView() {
+        updateDisplayName();
+        String id = getViewStringIdentifier();
+        if (!createdComponents.containsKey(id)) {
+            CompilationViewer newViewer = createViewer(activeFactory);
+            createdComponents.put(id, newViewer);
+            viewerPanel.add(newViewer.getComponent(), id);
+        }
+
+        CompilationViewer newViewer = createdComponents.get(id);
+        if (newViewer != activeViewer) {
+            activeViewer = newViewer;
+            viewerPanelCardLayout.show(viewerPanel, id);
+
+            currentLookup = new ProxyLookup(activeViewer.getLookup(), Lookups.fixed(getFirstGraph(), getSecondGraph()));
+            initializeToolBar(activeFactory.getName());
+
+            // Make sure that lookup is updated.
+            proxyLookup.lookup(Object.class);
+        }
+    }
+
+    private String getViewStringIdentifier() {
+        return String.format("%s/%d/%d", activeFactory.getName(), getModel().getFirstPosition(), getModel().getSecondPosition());
+    }
+
+    private AbstractButton createFactoryChangeButton(final CompilationViewerFactory factory) {
+        JToggleButton toggleButton = new JToggleButton(factory.getName());
+        toggleButton.addActionListener(new ActionListener() {
+
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                activateFactory(factory);
+            }
+        });
+        return toggleButton;
+    }
+
+    private CompilationViewer createViewer(CompilationViewerFactory activeFactory) {
+        InputGraph firstSnapshot = getFirstGraph();
+        InputGraph secondSnapshot = getSecondGraph();
+        return activeFactory.createViewer(firstSnapshot, secondSnapshot);
+    }
+
+    private void initializeToolBar(String id) {
+        viewerToolBar.removeAll();
+        for (Action a : LookupUtils.lookupActions(String.format("CompilationViewer/%s/Actions", id), activeViewer.getLookup())) {
+            if (a instanceof Presenter.Toolbar) {
+                viewerToolBar.add(((Presenter.Toolbar) a).getToolbarPresenter());
+            } else {
+                viewerToolBar.add(a);
+            }
+        }
+        viewerToolBar.updateUI();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/GraphViewerImplementation.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,41 @@
+/*
+ * 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.oracle.graal.visualizer.editor;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.services.GraphViewer;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class GraphViewerImplementation implements GraphViewer {
+
+    @Override
+    public void view(InputGraph graph) {
+        EditorTopComponent tc = new EditorTopComponent(graph);
+        tc.open();
+        tc.requestActive();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/NodeQuickSearch.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,143 @@
+/*
+ * 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.oracle.graal.visualizer.editor;
+
+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 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 = null;// TODO: FIXME 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) {
+                                // TODO: find connection again!
+                                //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);
+                                    // TODO: find connection again!
+                                    //comp.setSelectedNodes(tmpSet);
+                                    comp.requestActive();
+                                }
+                            }
+                        },
+                        n.getProperties().get(name) + " (" + n.getId() + " " + n.getProperties().get("name") + ")"
+                    );
+                }
+            }
+        } else {
+            System.out.println("no input graph provider!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/SplitCompilationViewer.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.editor;
+
+import com.sun.hotspot.igv.graph.Figure;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Collection;
+import java.util.prefs.Preferences;
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+import javax.swing.JToolBar;
+import org.openide.util.Lookup;
+import org.openide.util.NbPreferences;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ProxyLookup;
+
+class SplitCompilationViewer implements CompilationViewer {
+
+    private JSplitPane splitPane;
+    private Component firstPanel;
+    private Component secondPanel;
+    private Lookup combinedLookup;
+    private static final String DIVIDER_LOCATION = "dividerLocation";
+    private final PropertyChangeListener splitChanged = new PropertyChangeListener() {
+
+        @Override
+        public void propertyChange(PropertyChangeEvent changeEvent) {
+            String propertyName = changeEvent.getPropertyName();
+            if (propertyName.equals(JSplitPane.DIVIDER_LOCATION_PROPERTY)) {
+                setLastDividerLocation((Integer) changeEvent.getNewValue());
+            }
+        }
+    };
+
+    private static void setLastDividerLocation(int pos) {
+        NbPreferences.forModule(SplitCompilationViewer.class).put(DIVIDER_LOCATION, Integer.toString(pos));
+    }
+
+    private static int getLastDividerLocation() {
+        try {
+            return Integer.parseInt(NbPreferences.forModule(SplitCompilationViewer.class).get(DIVIDER_LOCATION, "400"));
+        } catch (NumberFormatException e) {
+            return 400;
+        }
+    }
+
+    public SplitCompilationViewer(CompilationViewer firstViewer, CompilationViewer secondViewer) {
+        splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+        firstPanel = createComponent(firstViewer);
+        secondPanel = createComponent(secondViewer);
+        splitPane.add(firstPanel);
+        splitPane.add(secondPanel);
+        splitPane.addPropertyChangeListener(splitChanged);
+        splitPane.setDividerLocation(getLastDividerLocation());
+        combinedLookup = new ProxyLookup(firstViewer.getLookup(), secondViewer.getLookup());
+    }
+
+    @Override
+    public Lookup getLookup() {
+        return combinedLookup;
+    }
+
+    @Override
+    public Component getComponent() {
+        return splitPane;
+    }
+
+    private Component createComponent(CompilationViewer viewer) {
+        return viewer.getComponent();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/SplitCompilationViewerFactory.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.editor;
+
+import com.sun.hotspot.igv.data.InputGraph;
+
+public abstract class SplitCompilationViewerFactory implements CompilationViewerFactory {
+
+    @Override
+    public CompilationViewer createViewer(InputGraph firstGraph, InputGraph secondGraph) {
+        if (firstGraph == secondGraph) {
+            return createViewer(firstGraph);
+        } else {
+            CompilationViewer firstViewer = createViewer(firstGraph);
+            CompilationViewer secondViewer = createViewer(secondGraph);
+            return new SplitCompilationViewer(firstViewer, secondViewer);
+        }
+    }
+
+    protected abstract CompilationViewer createViewer(InputGraph graph);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/layer.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,17 @@
+<?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="QuickSearch">
+        <folder name="Nodes">
+            <attr name="command" stringvalue="n"/>
+            <attr name="position" intvalue="0"/>
+            <file name="com-oracle-graal-visualizer-editor-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>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.filter" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.filter.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.filter
+OpenIDE-Module-Layer: com/sun/hotspot/igv/filter/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/filter/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.filter-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=7c032ebf
+build.xml.script.CRC32=3b022a25
+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=7c032ebf
+nbproject/build-impl.xml.script.CRC32=26513f91
+nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,104 @@
+<?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.filter</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>
+                <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.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>
+                    <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.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.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>
+                <package>com.sun.hotspot.igv.filter</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/AbstractFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,63 @@
+/*
+ * 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.data.ChangedEvent;
+import com.sun.hotspot.igv.data.Properties;
+import org.openide.cookies.OpenCookie;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public abstract class AbstractFilter implements Filter {
+
+    private ChangedEvent<Filter> changedEvent;
+    private Properties properties;
+
+    public AbstractFilter() {
+        changedEvent = new ChangedEvent<Filter>(this);
+        properties = new Properties();
+    }
+
+    @Override
+    public Properties getProperties() {
+        return properties;
+    }
+
+    @Override
+    public OpenCookie getEditor() {
+        return null;
+    }
+
+    @Override
+    public ChangedEvent<Filter> getChangedEvent() {
+        return changedEvent;
+    }
+
+    protected void fireChangedEvent() {
+        changedEvent.fire();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,11 @@
+OpenIDE-Module-Name=Filter
+
+jLabel1.text=Name\:
+jLabel2.text=Source\:
+
+nameTextField.text=
+
+jButton1.text=OK
+jButton2.text=Cancel
+
+title=Edit Filter Dialog
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/ColorFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,136 @@
+/*
+ * 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.data.Properties;
+import com.sun.hotspot.igv.graph.Connection.ConnectionStyle;
+import com.sun.hotspot.igv.graph.*;
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ColorFilter extends AbstractFilter {
+
+    private List<ColorRule> colorRules;
+    private String name;
+
+    public ColorFilter(String name) {
+        this.name = name;
+        colorRules = new ArrayList<>();
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void apply(Diagram diagram) {
+
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures());
+        for (ColorRule rule : colorRules) {
+            if (rule.getSelector() != null) {
+                List<Figure> figures = rule.getSelector().selected(diagram);
+                for (Figure f : figures) {
+                    applyRule(rule, f);
+                    if (rule.getColor() != null) {
+                        f.setColor(rule.getColor());
+                    }
+                }
+            } else {
+                for (Figure f : diagram.getFigures()) {
+                    applyRule(rule, f);
+                }
+            }
+        }
+    }
+
+    private void applyRule(ColorRule rule, Figure f) {
+        if (rule.getColor() != null) {
+            f.setColor(rule.getColor());
+        }
+        Color color = rule.getLineColor();
+        ConnectionStyle style = rule.getLineStyle();
+
+        for (OutputSlot s : f.getOutputSlots()) {
+            for (Connection c : s.getConnections()) {
+                if (color != null) {
+                    c.setColor(color);
+                }
+
+                if (style != null) {
+                    c.setStyle(style);
+                }
+            }
+        }
+    }
+
+    public void addRule(ColorRule r) {
+        colorRules.add(r);
+    }
+
+    public static class ColorRule {
+
+        private Color color;
+        private Color lineColor;
+        private Connection.ConnectionStyle lineStyle;
+        private Selector selector;
+
+        public ColorRule(Selector selector, Color c) {
+            this(selector, c, null, null);
+        }
+
+        public ColorRule(Selector selector, Color c, Color lineColor, Connection.ConnectionStyle lineStyle) {
+            this.selector = selector;
+            this.color = c;
+            this.lineColor = lineColor;
+            this.lineStyle = lineStyle;
+
+        }
+
+        public ColorRule(Color c) {
+            this(null, c);
+        }
+
+        public Color getColor() {
+            return color;
+        }
+
+        public Selector getSelector() {
+            return selector;
+        }
+
+        public Color getLineColor() {
+            return lineColor;
+        }
+
+        public Connection.ConnectionStyle getLineStyle() {
+            return lineStyle;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,221 @@
+/*
+ * 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.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;
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class CombineFilter extends AbstractFilter {
+
+    private List<CombineRule> rules;
+    private String name;
+
+    public CombineFilter(String name) {
+        this.name = name;
+        rules = new ArrayList<>();
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void apply(Diagram diagram) {
+
+        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<>();
+            for (Figure f : list) {
+
+                List<Figure> successors = new ArrayList<>(f.getSuccessors());
+                if (r.isReversed()) {
+                    if (successors.size() == 1) {
+                        Figure succ = successors.get(0);
+                        InputSlot slot = null;
+
+                        for (InputSlot s : succ.getInputSlots()) {
+                            for (Connection c : s.getConnections()) {
+                                if (c.getOutputSlot().getFigure() == f) {
+                                    slot = s;
+                                }
+                            }
+                        }
+
+                        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 {
+                            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(), c.getLabel());
+                                newConn.setColor(c.getColor());
+                                newConn.setStyle(c.getStyle());
+                            }
+                        }
+
+                        figuresToRemove.add(f);
+                    }
+                } else {
+
+                    for (Figure succ : successors) {
+                        if (succ.getPredecessors().size() == 1 && succ.getInputSlots().size() == 1) {
+                            if (succ.getProperties().selectSingle(r.getSecondMatcher()) != null && succ.getOutputSlots().size() == 1) {
+
+
+                                OutputSlot oldSlot = null;
+                                for (OutputSlot s : f.getOutputSlots()) {
+                                    for (Connection c : s.getConnections()) {
+                                        if (c.getInputSlot().getFigure() == succ) {
+                                            oldSlot = s;
+                                        }
+                                    }
+                                }
+
+                                assert oldSlot != null;
+
+                                OutputSlot nextSlot = succ.getOutputSlots().get(0);
+                                int pos = 0;
+                                if (succ.getProperties().get("con") != null) {
+                                    pos = Integer.parseInt(succ.getProperties().get("con"));
+                                }
+                                OutputSlot slot = f.createOutputSlot(pos);
+                                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 {
+                                    slot.setText(succ.getProperties().get("dump_spec"));
+                                    if (succ.getProperties().get("short_name") != null) {
+                                        slot.setShortName(succ.getProperties().get("short_name"));
+                                    } else {
+                                        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, c.getLabel());
+                                    newConn.setColor(c.getColor());
+                                    newConn.setStyle(c.getStyle());
+                                }
+
+
+                                figuresToRemove.add(succ);
+
+                                if (oldSlot.getConnections().size() == 0) {
+                                    f.removeSlot(oldSlot);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            diagram.removeAllFigures(figuresToRemove);
+        }
+    }
+
+    public void addRule(CombineRule combineRule) {
+        rules.add(combineRule);
+    }
+
+    public static class CombineRule {
+
+        private PropertyMatcher first;
+        private PropertyMatcher second;
+        private boolean reversed;
+        private String shortProperty;
+
+        public CombineRule(PropertyMatcher first, PropertyMatcher second) {
+            this(first, second, false);
+
+        }
+
+        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() {
+            return reversed;
+        }
+
+        public PropertyMatcher getFirstMatcher() {
+            return first;
+        }
+
+        public PropertyMatcher getSecondMatcher() {
+            return second;
+        }
+
+        public String getShortProperty() {
+            return shortProperty;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,104 @@
+/*
+ * 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.data.Properties;
+import com.sun.hotspot.igv.graph.*;
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ConnectionFilter extends AbstractFilter {
+
+    private List<ConnectionStyleRule> connectionStyleRules;
+    private String name;
+
+    public ConnectionFilter(String name) {
+        this.name = name;
+        connectionStyleRules = new ArrayList<>();
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void apply(Diagram diagram) {
+
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures());
+        for (ConnectionStyleRule rule : connectionStyleRules) {
+            List<Figure> figures = null;
+            if (rule.getSelector() != null) {
+                figures = rule.getSelector().selected(diagram);
+            } else {
+                figures = diagram.getFigures();
+            }
+
+            for (Figure f : figures) {
+                for (OutputSlot os : f.getOutputSlots()) {
+                    for (Connection c : os.getConnections()) {
+                        if (figures.contains(c.getInputSlot().getFigure())) {
+                            c.setStyle(rule.getLineStyle());
+                            c.setColor(rule.getLineColor());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public void addRule(ConnectionStyleRule r) {
+        connectionStyleRules.add(r);
+    }
+
+    public static class ConnectionStyleRule {
+
+        private Color lineColor;
+        private Connection.ConnectionStyle lineStyle;
+        private Selector selector;
+
+        public ConnectionStyleRule(Selector selector, Color lineColor, Connection.ConnectionStyle lineStyle) {
+            this.selector = selector;
+            this.lineColor = lineColor;
+            this.lineStyle = lineStyle;
+        }
+
+        public Selector getSelector() {
+            return selector;
+        }
+
+        public Color getLineColor() {
+            return lineColor;
+        }
+
+        public Connection.ConnectionStyle getLineStyle() {
+            return lineStyle;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1998, 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.  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 java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.script.*;
+import org.openide.cookies.OpenCookie;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class CustomFilter extends AbstractFilter {
+
+    public static final String JAVASCRIPT_HELPER_ID = "JavaScriptHelper";
+    private String code;
+    private String name;
+
+    public CustomFilter(String name, String code) {
+        this.name = name;
+        this.code = code;
+        getProperties().setProperty("name", name);
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setName(String s) {
+        name = s;
+        fireChangedEvent();
+    }
+
+    public void setCode(String s) {
+        code = s;
+        fireChangedEvent();
+    }
+
+    @Override
+    public OpenCookie getEditor() {
+        return new OpenCookie() {
+
+            @Override
+            public void open() {
+                openInEditor();
+            }
+        };
+    }
+
+    public boolean openInEditor() {
+        EditFilterDialog dialog = new EditFilterDialog(CustomFilter.this);
+        dialog.setVisible(true);
+        boolean result = dialog.wasAccepted();
+        this.getChangedEvent().fire();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return getName();
+    }
+
+    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);");
+        try {
+            FileObject fo = FileUtil.getConfigRoot().getFileObject(JAVASCRIPT_HELPER_ID);
+            is = fo.getInputStream();
+            BufferedReader r = new BufferedReader(new InputStreamReader(is));
+            String s;
+            while ((s = r.readLine()) != null) {
+                sb.append(s);
+                sb.append("\n");
+            }
+
+        } catch (IOException ex) {
+            Logger.getLogger("global").log(Level.SEVERE, null, ex);
+        } finally {
+            try {
+                is.close();
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public void apply(Diagram d) {
+        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/visualizer/Filter/src/com/sun/hotspot/igv/filter/EdgeColorIndexFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.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++;
+            }
+
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.form	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
+  <Properties>
+    <Property name="defaultCloseOperation" type="int" value="2"/>
+    <Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+      <ResourceString bundle="at/ssw/graphanalyzer/filter/Bundle.properties" key="title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+    </Property>
+    <Property name="resizable" type="boolean" value="false"/>
+  </Properties>
+  <SyntheticProperties>
+    <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
+  </SyntheticProperties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="1" attributes="0">
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Component id="sourceLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                          <Component id="nameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                      <EmptySpace min="-2" pref="25" max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Component id="jScrollPane1" pref="695" max="32767" attributes="1"/>
+                          <Component id="nameTextField" alignment="0" pref="695" max="32767" attributes="1"/>
+                      </Group>
+                  </Group>
+                  <Group type="102" alignment="1" attributes="0">
+                      <Component id="okButton" min="-2" pref="76" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="cancelButton" min="-2" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="nameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="nameTextField" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace type="unrelated" max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="sourceLabel" min="-2" max="-2" attributes="0"/>
+                  <Component id="jScrollPane1" min="-2" pref="337" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace pref="16" max="32767" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JTextArea" name="sourceTextArea">
+          <Properties>
+            <Property name="columns" type="int" value="20"/>
+            <Property name="rows" type="int" value="5"/>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JTextField" name="nameTextField">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="at/ssw/graphanalyzer/coordinator/Bundle.properties" key="nameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="nameLabel">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="at/ssw/graphanalyzer/filter/Bundle.properties" key="jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="sourceLabel">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="at/ssw/graphanalyzer/filter/Bundle.properties" key="jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JButton" name="okButton">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="at/ssw/graphanalyzer/filter/Bundle.properties" key="jButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonClicked,okButtonClicked"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JButton" name="cancelButton">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="at/ssw/graphanalyzer/filter/Bundle.properties" key="jButton2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonClicked"/>
+      </Events>
+    </Component>
+  </SubComponents>
+</Form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,161 @@
+/*
+ * 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 org.openide.windows.WindowManager;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class EditFilterDialog extends javax.swing.JDialog {
+
+    private CustomFilter customFilter;
+    private boolean accepted;
+
+    /** Creates new form EditFilterDialog */
+    public EditFilterDialog(CustomFilter customFilter) {
+        super(WindowManager.getDefault().getMainWindow(), true);
+        this.customFilter = customFilter;
+        initComponents();
+
+        sourceTextArea.setText(customFilter.getCode());
+        nameTextField.setText(customFilter.getName());
+    }
+
+    public boolean wasAccepted() {
+        return accepted;
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jScrollPane1 = new javax.swing.JScrollPane();
+        sourceTextArea = new javax.swing.JTextArea();
+        nameTextField = new javax.swing.JTextField();
+        nameLabel = new javax.swing.JLabel();
+        sourceLabel = new javax.swing.JLabel();
+        okButton = new javax.swing.JButton();
+        cancelButton = new javax.swing.JButton();
+
+        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+        setTitle(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "title")); // NOI18N
+        setResizable(false);
+
+        sourceTextArea.setColumns(20);
+        sourceTextArea.setRows(5);
+        jScrollPane1.setViewportView(sourceTextArea);
+
+        nameTextField.setText("null");
+
+        nameLabel.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jLabel1.text")); // NOI18N
+
+        sourceLabel.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jLabel2.text")); // NOI18N
+
+        okButton.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jButton1.text")); // NOI18N
+        okButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                cancelButtonClicked(evt);
+                okButtonClicked(evt);
+            }
+        });
+
+        cancelButton.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jButton2.text")); // NOI18N
+        cancelButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                cancelButtonClicked(evt);
+            }
+        });
+
+        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
+        getContentPane().setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(layout.createSequentialGroup()
+                .addContainerGap()
+                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
+                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                            .add(sourceLabel)
+                            .add(nameLabel))
+                        .add(25, 25, 25)
+                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                            .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 695, Short.MAX_VALUE)
+                            .add(nameTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 695, Short.MAX_VALUE)))
+                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
+                        .add(okButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 76, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+                        .add(cancelButton)))
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(layout.createSequentialGroup()
+                .addContainerGap()
+                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                    .add(nameLabel)
+                    .add(nameTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
+                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(sourceLabel)
+                    .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 337, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 16, Short.MAX_VALUE)
+                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                    .add(cancelButton)
+                    .add(okButton))
+                .addContainerGap())
+        );
+
+        pack();
+    }// </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);
+}//GEN-LAST:event_okButtonClicked
+
+private void cancelButtonClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonClicked
+	setVisible(false);
+}//GEN-LAST:event_cancelButtonClicked
+	
+	
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JButton cancelButton;
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JLabel nameLabel;
+    private javax.swing.JTextField nameTextField;
+    private javax.swing.JButton okButton;
+    private javax.swing.JLabel sourceLabel;
+    private javax.swing.JTextArea sourceTextArea;
+    // End of variables declaration//GEN-END:variables
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/Filter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.filter;
+
+import com.sun.hotspot.igv.data.ChangedEvent;
+import com.sun.hotspot.igv.data.ChangedEventProvider;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.graph.Diagram;
+import org.openide.cookies.OpenCookie;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface Filter extends Properties.Provider, ChangedEventProvider<Filter> {
+
+    public String getName();
+
+    public void apply(Diagram d);
+
+    OpenCookie getEditor();
+
+    @Override
+    ChangedEvent<Filter> getChangedEvent();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChain.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,135 @@
+/*
+ * 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.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;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class FilterChain implements ChangedEventProvider<FilterChain> {
+
+    private List<Filter> filters;
+    private transient ChangedEvent<FilterChain> changedEvent;
+    
+    private ChangedListener<Filter> changedListener = new ChangedListener<Filter>() {
+        @Override
+        public void changed(Filter source) {
+            changedEvent.fire();
+        }
+    };
+
+    public FilterChain() {
+        filters = new ArrayList<>();
+        changedEvent = new ChangedEvent<>(this);
+    }
+
+    public FilterChain(FilterChain f) {
+        this.filters = new ArrayList<>(f.filters);
+        changedEvent = new ChangedEvent<>(this);
+    }
+
+    @Override
+    public ChangedEvent<FilterChain> getChangedEvent() {
+        return changedEvent;
+    }
+
+    public Filter getFilterAt(int index) {
+        assert index >= 0 && index < filters.size();
+        return filters.get(index);
+    }
+
+    public void apply(Diagram d) {
+        for (Filter f : filters) {
+            f.apply(d);
+        }
+    }
+
+    public void apply(Diagram d, FilterChain sequence) {
+        List<Filter> applied = new ArrayList<>();
+        for (Filter f : sequence.getFilters()) {
+            if (filters.contains(f)) {
+                f.apply(d);
+                applied.add(f);
+            }
+        }
+
+
+        for (Filter f : filters) {
+            if (!applied.contains(f)) {
+                f.apply(d);
+            }
+        }
+    }
+
+
+    public void addFilter(Filter filter) {
+        assert filter != null;
+        filters.add(filter);
+        filter.getChangedEvent().addListener(changedListener);
+        changedEvent.fire();
+    }
+
+    public boolean containsFilter(Filter filter) {
+        return filters.contains(filter);
+    }
+
+    public void removeFilter(Filter filter) {
+        assert filters.contains(filter);
+        filters.remove(filter);
+        filter.getChangedEvent().removeListener(changedListener);
+        changedEvent.fire();
+    }
+
+    public void moveFilterUp(Filter filter) {
+        assert filters.contains(filter);
+        int index = filters.indexOf(filter);
+        if (index != 0) {
+            filters.remove(index);
+            filters.add(index - 1, filter);
+        }
+        changedEvent.fire();
+    }
+
+    public void moveFilterDown(Filter filter) {
+        assert filters.contains(filter);
+        int index = filters.indexOf(filter);
+        if (index != filters.size() - 1) {
+            filters.remove(index);
+            filters.add(index + 1, filter);
+        }
+        changedEvent.fire();
+    }
+
+    public List<Filter> getFilters() {
+        return Collections.unmodifiableList(filters);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChainProvider.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface FilterChainProvider {
+
+    public FilterChain getFilterChain();
+
+    public FilterChain getSequence();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterSetting.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.filter;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class FilterSetting {
+
+    private Set<Filter> filters;
+    private String name;
+
+    public FilterSetting() {
+        this(null);
+    }
+
+    public FilterSetting(String name) {
+        this.name = name;
+        filters = new HashSet<>();
+    }
+
+    public Set<Filter> getFilters() {
+        return Collections.unmodifiableSet(filters);
+    }
+
+    public void addFilter(Filter f) {
+        assert !filters.contains(f);
+        filters.add(f);
+    }
+
+    public void removeFilter(Filter f) {
+        assert filters.contains(f);
+        filters.remove(f);
+    }
+
+    public boolean containsFilter(Filter f) {
+        return filters.contains(f);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getFilterCount() {
+        return filters.size();
+    }
+
+    @Override
+    public String toString() {
+        return getName();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/GradientColorFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,104 @@
+/*
+ * 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;
+import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.graph.Selector;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class RemoveFilter extends AbstractFilter {
+
+    private List<RemoveRule> rules;
+    private String name;
+
+    public RemoveFilter(String name) {
+        this.name = name;
+        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);
+
+            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);
+            }
+
+            diagram.removeAllFigures(toRemove);
+        }
+    }
+
+    public void addRule(RemoveRule rule) {
+        rules.add(rule);
+    }
+
+    public static class RemoveRule {
+
+        private Selector selector;
+        private boolean removeOrphans;
+
+        public RemoveRule(Selector selector) {
+            this(selector, false);
+        }
+
+        public RemoveRule(Selector selector, boolean removeOrphans) {
+            this.selector = selector;
+            this.removeOrphans = removeOrphans;
+        }
+
+        public Selector getSelector() {
+            return selector;
+        }
+
+        public boolean getRemoveOrphans() {
+            return removeOrphans;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveInputsFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,140 @@
+/*
+ * 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.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class RemoveInputsFilter extends AbstractFilter {
+
+    private List<RemoveInputsRule> rules;
+    private String name;
+
+    public RemoveInputsFilter(String name) {
+        this.name = name;
+        rules = new ArrayList<>();
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void apply(Diagram diagram) {
+
+        for (RemoveInputsRule r : rules) {
+
+            List<Figure> list = r.getSelector().selected(diagram);
+            for (Figure f : list) {
+                int z = 0;
+                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();
+                        List<Connection> conns = is.getConnections();
+                        for (int i = 0; i < conns.size(); i++) {
+                            Connection c = conns.get(i);
+                            OutputSlot os = c.getOutputSlot();
+                            Figure pred = os.getFigure();
+                            if (i != 0) {
+                                sb.append("<BR>");
+                            }
+                            sb.append(pred.getLines()[0]);
+                        }
+                        is.removeAllConnections();
+                        is.setShortName("X");
+                        is.setText(sb.toString());
+                        last.add(is);
+                    } else {
+                        last.clear();
+                    }
+                    z++;
+                }
+
+                if (last.size() > 3) {
+                    InputSlot first = last.get(0);
+                    first.setShortName("XX");
+
+                    StringBuilder sb = new StringBuilder();
+                    for (int i = 0; i < last.size(); i++) {
+                        InputSlot is2 = last.get(i);
+                        if (i != 0) {
+                            sb.append("<BR>");
+                        }
+                        sb.append(is2.getText());
+                    }
+
+                    first.setText(sb.toString());
+
+                    for (int i = 1; i < last.size(); i++) {
+                        f.removeSlot(last.get(i));
+                    }
+                }
+            }
+        }
+    }
+
+    public void addRule(RemoveInputsRule rule) {
+        rules.add(rule);
+    }
+
+    public static class RemoveInputsRule {
+
+        private Selector selector;
+        private int startingIndex;
+        private int endIndex;
+
+        public RemoveInputsRule(Selector selector) {
+            this(selector, 0);
+        }
+
+        public RemoveInputsRule(Selector selector, int startIndex) {
+            this(selector, startIndex, Integer.MAX_VALUE);
+        }
+
+        public RemoveInputsRule(Selector selector, int startIndex, int endIndex) {
+            this.startingIndex = startIndex;
+            this.endIndex = endIndex;
+            this.selector = selector;
+        }
+
+        public int getStartingIndex() {
+            return startingIndex;
+        }
+
+        public int getEndIndex() {
+            return endIndex;
+        }
+
+        public Selector getSelector() {
+            return selector;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveSelfLoopsFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,78 @@
+/*
+ * 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.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class RemoveSelfLoopsFilter extends AbstractFilter {
+
+    private String name;
+
+    /** Creates a new instance of RemoveSelfLoops */
+    public RemoveSelfLoopsFilter(String name) {
+        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<>();
+                for (Connection c : is.getConnections()) {
+
+                    if (c.getOutputSlot().getFigure() == f) {
+                        toRemove.add(c);
+                    }
+                }
+
+                for (Connection c : toRemove) {
+
+                    c.remove();
+
+                    OutputSlot os = c.getOutputSlot();
+                    if (os.getConnections().size() == 0) {
+                        f.removeSlot(os);
+                    }
+
+                    c.getInputSlot().setShortName("O");
+                    c.getInputSlot().setText("Self Loop");
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,92 @@
+/*
+ * 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.*;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class SplitFilter extends AbstractFilter {
+
+    private String name;
+    private Selector selector;
+    private String propertyName;
+
+    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();
+                    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);
+                    }
+                }
+            }
+
+            d.removeFigure(f);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/UnconnectedSlotFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.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);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/helper.js	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ *
+ */
+ 
+ /**
+ *
+ * @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); 
+}
+
+function remove(property, regexp) {
+    var f = new RemoveFilter("");
+    f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp))));
+    f.apply(graph);
+}
+
+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);
+}
+
+function removeInputs(property, regexp, from, to) {
+    var f = new RemoveInputsFilter("");
+    if(from == undefined && to == undefined) {
+        f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp))));
+    } else if(to == undefined) {
+        f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), from));
+    } else {
+        f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), from, to));
+    }
+    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;
+var darkGray = Color.darkGray;
+var gray = Color.gray;
+var green = Color.green;
+var lightGray = Color.lightGray;
+var magenta = Color.magenta;
+var orange = Color.orange;
+var pink = Color.pink
+var red = Color.red;
+var yellow = Color.yellow;
+var white = Color.white;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/layer.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,5 @@
+<?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>
+        <file name="JavaScriptHelper" url="helper.js"/>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.filterwindow" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.filterwindow.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.filterwindow
+OpenIDE-Module-Layer: com/sun/hotspot/igv/filterwindow/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/filterwindow/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.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>
+    <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/visualizer/FilterWindow/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -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=09ba2a87
+nbproject/build-impl.xml.script.CRC32=e4293f0e
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,117 @@
+<?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.filterwindow</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.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.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.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>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/META-INF/services/com.sun.hotspot.igv.filter.FilterChainProvider	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+com.sun.hotspot.igv.filterwindow.FilterChainProviderImplementation
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,3 @@
+OpenIDE-Module-Name=FilterWindow
+CTL_FilterTopComponent=Filters
+HINT_FilterTopComponent=Allows to choose active filters and modify them.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckListView.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,52 @@
+/*
+ * 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.filterwindow;
+
+import javax.swing.JList;
+import org.openide.explorer.view.ListView;
+import org.openide.explorer.view.NodeListModel;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class CheckListView extends ListView {
+
+    @Override
+    public void showSelection(int[] indices) {
+        super.showSelection(indices);
+    }
+
+    @Override
+    protected NodeListModel createModel() {
+        return new CheckNodeListModel();
+    }
+
+    @Override
+    protected JList<Object> createList() {
+        JList<Object> tmpList = super.createList();
+        tmpList.setCellRenderer(new CheckRenderer(tmpList));
+        return tmpList;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNode.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,70 @@
+/*
+ * 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.filterwindow;
+
+import com.sun.hotspot.igv.data.ChangedEvent;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class CheckNode extends AbstractNode {
+
+    private ChangedEvent<CheckNode> selectionChangedEvent;
+    public boolean selected;
+    public boolean enabled;
+
+    public CheckNode(Children c, Lookup lookup) {
+        super(c, lookup);
+        selectionChangedEvent = new ChangedEvent<>(this);
+        selected = false;
+        enabled = true;
+    }
+
+    public ChangedEvent<CheckNode> getSelectionChangedEvent() {
+        return selectionChangedEvent;
+    }
+
+    public boolean isSelected() {
+        return selected;
+    }
+
+    public void setSelected(boolean b) {
+        if (b != selected) {
+            selected = b;
+            selectionChangedEvent.fire();
+        }
+    }
+
+    public void setEnabled(boolean b) {
+        enabled = b;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNodeListModel.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,42 @@
+/*
+ * 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.filterwindow;
+
+import org.openide.explorer.view.NodeListModel;
+import org.openide.explorer.view.Visualizer;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class CheckNodeListModel extends NodeListModel {
+
+    public CheckNode getCheckNodeAt(int index) {
+        Object item = getElementAt(index);
+        if (item != null) {
+            return (CheckNode) Visualizer.findNode(item);
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckRenderer.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,85 @@
+/*
+ * 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.filterwindow;
+
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import javax.swing.JCheckBox;
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+
+/**
+ * @author Thomas Wuerthinger
+ */
+public class CheckRenderer extends JCheckBox implements ListCellRenderer<Object> {
+
+    private JList<Object> list;
+    private Color startBackground;
+
+    public CheckRenderer(final JList<Object> list) {
+        this.list = list;
+        list.addMouseListener(
+                new MouseAdapter() {
+
+                    @Override
+                    public void mouseClicked(MouseEvent e) {
+                        int index = list.locationToIndex(e.getPoint());
+                        Point p2 = list.indexToLocation(index);
+                        Rectangle r = new Rectangle(p2.x, p2.y, getPreferredSize().height, getPreferredSize().height);
+                        if (r.contains(e.getPoint())) {
+                            CheckNode node = ((CheckNodeListModel) list.getModel()).getCheckNodeAt(index);
+                            node.setSelected(!node.isSelected());
+                            list.repaint();
+                            e.consume();
+                        }
+                    }
+                });
+
+        this.setPreferredSize(new Dimension(getPreferredSize().width, getPreferredSize().height - 5));
+        startBackground = this.getBackground();
+    }
+
+    @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());
+        this.setEnabled(list.isEnabled());
+
+        if (isSelected && list.hasFocus()) {
+            this.setBackground(list.getSelectionBackground());
+            this.setForeground(list.getSelectionForeground());
+        } else if (isSelected) {
+            assert !list.hasFocus();
+            this.setBackground(startBackground);
+            this.setForeground(list.getForeground());
+
+        } else {
+            this.setBackground(list.getBackground());
+            this.setForeground(list.getForeground());
+        }
+        return this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterChainProviderImplementation.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,44 @@
+/*
+ * 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.filterwindow;
+
+import com.sun.hotspot.igv.filter.FilterChain;
+import com.sun.hotspot.igv.filter.FilterChainProvider;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class FilterChainProviderImplementation implements FilterChainProvider {
+
+    @Override
+    public FilterChain getFilterChain() {
+        return FilterTopComponent.findInstance().getFilterChain();
+    }
+
+    @Override
+    public FilterChain getSequence() {
+        return FilterTopComponent.findInstance().getSequence();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterNode.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,117 @@
+/*
+ * 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.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.util.PropertiesSheet;
+import javax.swing.Action;
+import org.openide.actions.OpenAction;
+import org.openide.nodes.Children;
+import org.openide.nodes.Sheet;
+import org.openide.util.Lookup;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+import org.openide.util.Utilities;
+import org.openide.util.lookup.AbstractLookup;
+import org.openide.util.lookup.InstanceContent;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class FilterNode extends CheckNode implements LookupListener, ChangedListener<FilterTopComponent> {
+
+    private Filter filter;
+    private Lookup.Result<FilterChain> result;
+
+    public FilterNode(Filter filter) {
+        this(filter, new InstanceContent());
+    }
+
+    private FilterNode(Filter filter, InstanceContent content) {
+        super(Children.LEAF, new AbstractLookup(content));
+        content.add(filter);
+
+        content.add(filter.getEditor());
+        this.filter = filter;
+        filter.getChangedEvent().addListener(new ChangedListener<Filter>() {
+
+            @Override
+            public void changed(Filter source) {
+                update();
+            }
+        });
+
+        update();
+
+        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() {
+        this.setDisplayName(filter.getName());
+    }
+
+    public Filter getFilter() {
+        return filter;
+    }
+
+    @Override
+    protected Sheet createSheet() {
+        Sheet s = super.createSheet();
+        PropertiesSheet.initializeSheet(getFilter().getProperties(), s);
+        return s;
+    }
+
+    @Override
+    public Action[] getActions(boolean b) {
+        return new Action[]{(Action) OpenAction.findObject(OpenAction.class, true), (Action) MoveFilterUpAction.findObject(MoveFilterUpAction.class, true), (Action) MoveFilterDownAction.findObject(MoveFilterDownAction.class, true), (Action) RemoveFilterAction.findObject(RemoveFilterAction.class, true)};
+    }
+
+    @Override
+    public Action getPreferredAction() {
+        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));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.form	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-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"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
+  </AuxValues>
+
+  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
+</Form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,670 @@
+/*
+ * 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.filterwindow;
+
+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.filterwindow.actions.*;
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+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.*;
+import org.openide.util.actions.SystemAction;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
+
+/**
+ * 
+ * @author Thomas Wuerthinger
+ */
+public final class FilterTopComponent extends TopComponent implements LookupListener, ExplorerManager.Provider {
+
+    private static FilterTopComponent instance;
+    public static final String FOLDER_ID = "Filters";
+    public static final String AFTER_ID = "after";
+    public static final String ENABLED_ID = "enabled";
+    public static final String PREFERRED_ID = "FilterTopComponent";
+    private CheckListView view;
+    private ExplorerManager manager;
+    private FilterChain filterChain;
+    private FilterChain sequence;
+    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();
+        }
+    };
+
+    public ChangedEvent<FilterTopComponent> getFilterSettingsChangedEvent() {
+        return filterSettingsChangedEvent;
+    }
+
+    public FilterChain getSequence() {
+        return sequence;
+    }
+
+    public void updateSelection() {
+        Node[] nodes = this.getExplorerManager().getSelectedNodes();
+        int[] arr = new int[nodes.length];
+        for (int i = 0; i < nodes.length; i++) {
+            int index = sequence.getFilters().indexOf(((FilterNode) nodes[i]).getFilter());
+            arr[i] = index;
+        }
+        view.showSelection(arr);
+    }
+
+    private void comboBoxSelectionChanged() {
+
+        Object o = comboBox.getSelectedItem();
+        if (o == null) {
+            return;
+        }
+        assert o instanceof FilterSetting;
+        FilterSetting s = (FilterSetting) o;
+
+        if (s != customFilterSetting) {
+            FilterChain chain = getFilterChain();
+            chain.getChangedEvent().beginAtomic();
+            List<Filter> toRemove = new ArrayList<>();
+            for (Filter f : chain.getFilters()) {
+                if (!s.containsFilter(f)) {
+                    toRemove.add(f);
+                }
+            }
+            for (Filter f : toRemove) {
+                chain.removeFilter(f);
+            }
+
+            for (Filter f : s.getFilters()) {
+                if (!chain.containsFilter(f)) {
+                    chain.addFilter(f);
+                }
+            }
+
+            chain.getChangedEvent().endAtomic();
+            filterSettingsChangedEvent.fire();
+        } else {
+            this.updateComboBoxSelection();
+        }
+
+        SystemAction.get(RemoveFilterSettingsAction.class).setEnabled(comboBox.getSelectedItem() != this.customFilterSetting);
+        SystemAction.get(SaveFilterSettingsAction.class).setEnabled(comboBox.getSelectedItem() == this.customFilterSetting);
+    }
+
+    private void updateComboBox() {
+        comboBox.removeAllItems();
+        comboBox.addItem(customFilterSetting);
+        for (FilterSetting s : filterSettings) {
+            comboBox.addItem(s);
+        }
+
+        this.updateComboBoxSelection();
+    }
+
+    public void addFilterSetting() {
+        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 profile \"" + name + "\" already exists, do you want to replace it?", "Filter");
+                    if (DialogDisplayer.getDefault().notify(conf) == NotifyDescriptor.YES_OPTION) {
+                        toRemove = s;
+                        break;
+                    } else {
+                        return;
+                    }
+                }
+            }
+
+            if (toRemove != null) {
+                filterSettings.remove(toRemove);
+            }
+            FilterSetting setting = createFilterSetting(name);
+            filterSettings.add(setting);
+
+            // Sort alphabetically
+            Collections.sort(filterSettings, new Comparator<FilterSetting>() {
+
+                @Override
+                public int compare(FilterSetting o1, FilterSetting o2) {
+                    return o1.getName().compareTo(o2.getName());
+                }
+            });
+
+            updateComboBox();
+        }
+    }
+
+    public boolean canRemoveFilterSetting() {
+        return comboBox.getSelectedItem() != customFilterSetting;
+    }
+
+    public void removeFilterSetting() {
+        if (canRemoveFilterSetting()) {
+            Object o = comboBox.getSelectedItem();
+            assert o instanceof FilterSetting;
+            FilterSetting f = (FilterSetting) o;
+            assert f != customFilterSetting;
+            assert filterSettings.contains(f);
+            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();
+            }
+        }
+    }
+
+    private FilterSetting createFilterSetting(String name) {
+        FilterSetting s = new FilterSetting(name);
+        FilterChain chain = this.getFilterChain();
+        for (Filter f : chain.getFilters()) {
+            s.addFilter(f);
+        }
+        return s;
+    }
+
+    private void updateComboBoxSelection() {
+        List<Filter> filters = this.getFilterChain().getFilters();
+        boolean found = false;
+        for (FilterSetting s : filterSettings) {
+            if (s.getFilterCount() == filters.size()) {
+                boolean ok = true;
+                for (Filter f : filters) {
+                    if (!s.containsFilter(f)) {
+                        ok = false;
+                    }
+                }
+
+                if (ok) {
+                    if (comboBox.getSelectedItem() != s) {
+                        comboBox.setSelectedItem(s);
+                    }
+                    found = true;
+                    break;
+                }
+            }
+        }
+
+        if (!found && comboBox.getSelectedItem() != customFilterSetting) {
+            comboBox.setSelectedItem(customFilterSetting);
+        }
+    }
+
+    private class FilterChildren extends Children.Keys<Filter> implements ChangedListener<CheckNode> {
+
+        private HashMap<Filter, Node> nodeHash = new HashMap<>();
+
+        @Override
+        protected Node[] createNodes(Filter filter) {
+            if (nodeHash.containsKey(filter)) {
+                return new Node[]{nodeHash.get(filter)};
+            }
+
+            FilterNode node = new FilterNode(filter);
+            node.getSelectionChangedEvent().addListener(this);
+            nodeHash.put(filter, node);
+            return new Node[]{node};
+        }
+
+        public FilterChildren() {
+            sequence.getChangedEvent().addListener(new ChangedListener<FilterChain>() {
+
+                @Override
+                public void changed(FilterChain source) {
+                    addNotify();
+                }
+            });
+
+            setBefore(false);
+        }
+
+        @Override
+        protected void addNotify() {
+            setKeys(sequence.getFilters());
+            updateSelection();
+        }
+
+        @Override
+        public void changed(CheckNode source) {
+            FilterNode node = (FilterNode) source;
+            Filter f = node.getFilter();
+            FilterChain chain = getFilterChain();
+            if (node.isSelected()) {
+                if (!chain.containsFilter(f)) {
+                    chain.addFilter(f);
+                }
+            } else {
+                if (chain.containsFilter(f)) {
+                    chain.removeFilter(f);
+                }
+            }
+            view.revalidate();
+            view.repaint();
+            updateComboBoxSelection();
+        }
+    }
+
+    public FilterChain getFilterChain() {
+        return filterChain;
+    }
+
+    private FilterTopComponent() {
+        filterSettingsChangedEvent = new ChangedEvent<>(this);
+        initComponents();
+        setName(NbBundle.getMessage(FilterTopComponent.class, "CTL_FilterTopComponent"));
+        setToolTipText(NbBundle.getMessage(FilterTopComponent.class, "HINT_FilterTopComponent"));
+        //        setIcon(Utilities.loadImage(ICON_PATH, true));
+
+        sequence = new FilterChain();
+        filterChain = new FilterChain();
+        initFilters();
+        manager = new ExplorerManager();
+        manager.setRootContext(new AbstractNode(new FilterChildren()));
+        associateLookup(ExplorerUtils.createLookup(manager, getActionMap()));
+        view = new CheckListView();
+
+        ToolbarPool.getDefault().setPreferredIconSize(16);
+        Toolbar toolBar = new Toolbar();
+        Border b = (Border) UIManager.get("Nb.Editor.Toolbar.border"); //NOI18N
+        toolBar.setBorder(b);
+        comboBox = new JComboBox();
+        toolBar.add(comboBox);
+        this.add(toolBar, BorderLayout.NORTH);
+        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()));
+        this.add(view, BorderLayout.CENTER);
+
+        filterSettings = new ArrayList<>();
+        updateComboBox();
+
+        comboBox.addActionListener(comboBoxActionListener);
+        setChain(filterChain);
+    }
+
+    public void newFilter() {
+        CustomFilter cf = new CustomFilter("My custom filter", "");
+        if (cf.openInEditor()) {
+            sequence.addFilter(cf);
+            FileObject fo = getFileObject(cf);
+            FilterChangedListener listener = new FilterChangedListener(fo, cf);
+            listener.changed(cf);
+            cf.getChangedEvent().addListener(listener);
+        }
+    }
+
+    public void removeFilter(Filter f) {
+        com.sun.hotspot.igv.filter.CustomFilter cf = (com.sun.hotspot.igv.filter.CustomFilter) f;
+
+        sequence.removeFilter(cf);
+        try {
+            getFileObject(cf).delete();
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+
+    }
+
+    private static class FilterChangedListener implements ChangedListener<Filter> {
+
+        private FileObject fileObject;
+        private CustomFilter filter;
+
+        public FilterChangedListener(FileObject fo, CustomFilter cf) {
+            fileObject = fo;
+            filter = cf;
+        }
+
+        @Override
+        public void changed(Filter source) {
+            try {
+                if (!fileObject.getName().equals(filter.getName())) {
+                    FileLock lock = fileObject.lock();
+                    fileObject.move(lock, fileObject.getParent(), filter.getName(), "");
+                    lock.releaseLock();
+                    FileObject newFileObject = fileObject.getParent().getFileObject(filter.getName());
+                    fileObject = newFileObject;
+                }
+
+                FileLock lock = fileObject.lock();
+                OutputStream os = fileObject.getOutputStream(lock);
+                try (Writer w = new OutputStreamWriter(os)) {
+                    String s = filter.getCode();
+                    w.write(s);
+                }
+                lock.releaseLock();
+
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+        }
+    }
+
+    public void initFilters() {
+        FileObject folder = FileUtil.getConfigRoot().getFileObject(FOLDER_ID);
+        FileObject[] children = folder.getChildren();
+
+        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;
+
+            String code = "";
+            FileLock lock = null;
+            try {
+                lock = fo.lock();
+                is = fo.getInputStream();
+                BufferedReader r = new BufferedReader(new InputStreamReader(is));
+                String s;
+                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) {
+                Exceptions.printStackTrace(ex);
+            } finally {
+                try {
+                    is.close();
+                } catch (IOException ex) {
+                    Exceptions.printStackTrace(ex);
+                }
+                lock.releaseLock();
+            }
+
+            String displayName = fo.getName();
+
+
+            final CustomFilter cf = new CustomFilter(displayName, code);
+            map.put(displayName, cf);
+
+            String after = (String) fo.getAttribute(AFTER_ID);
+            afterMap.put(cf, after);
+
+            Boolean enabled = (Boolean) fo.getAttribute(ENABLED_ID);
+            if (enabled != null && (boolean) enabled) {
+                enabledSet.add(cf);
+            }
+
+            cf.getChangedEvent().addListener(new FilterChangedListener(fo, cf));
+
+            customFilters.add(cf);
+        }
+
+        for (int j = 0; j < customFilters.size(); j++) {
+            for (int i = 0; i < customFilters.size(); i++) {
+                List<CustomFilter> copiedList = new ArrayList<>(customFilters);
+                for (CustomFilter cf : copiedList) {
+
+                    String after = afterMap.get(cf);
+
+                    if (map.containsKey(after)) {
+                        CustomFilter afterCf = map.get(after);
+                        int index = customFilters.indexOf(afterCf);
+                        int currentIndex = customFilters.indexOf(cf);
+
+                        if (currentIndex < index) {
+                            customFilters.remove(currentIndex);
+                            customFilters.add(index, cf);
+                        }
+                    }
+                }
+            }
+        }
+
+        for (CustomFilter cf : customFilters) {
+            sequence.addFilter(cf);
+            if (enabledSet.contains(cf)) {
+                filterChain.addFilter(cf);
+            }
+        }
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        setLayout(new java.awt.BorderLayout());
+
+    }// </editor-fold>//GEN-END:initComponents
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    // End of variables declaration//GEN-END:variables
+    /**
+     * Gets default instance. Do not use directly: reserved for *.settings files only,
+     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
+     * To obtain the singleton instance, use {@link findInstance}.
+     */
+    public static synchronized FilterTopComponent getDefault() {
+        if (instance == null) {
+            instance = new FilterTopComponent();
+        }
+        return instance;
+    }
+
+    /**
+     * Obtain the FilterTopComponent instance. Never call {@link #getDefault} directly!
+     */
+    public static synchronized FilterTopComponent findInstance() {
+        TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
+        if (win == null) {
+            ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot find Filter component. It will not be located properly in the window system.");
+            return getDefault();
+        }
+        if (win instanceof FilterTopComponent) {
+            return (FilterTopComponent) win;
+        }
+        ErrorManager.getDefault().log(ErrorManager.WARNING, "There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior.");
+        return getDefault();
+    }
+
+    @Override
+    public int getPersistenceType() {
+        return TopComponent.PERSISTENCE_ALWAYS;
+    }
+
+    @Override
+    protected String preferredID() {
+        return PREFERRED_ID;
+    }
+
+    @Override
+    public ExplorerManager getExplorerManager() {
+        return manager;
+    }
+
+    @Override
+    public void componentOpened() {
+        Lookup.Template<FilterChain> tpl = new Lookup.Template<>(FilterChain.class);
+        result = Utilities.actionsGlobalContext().lookup(tpl);
+        result.addLookupListener(this);
+    }
+
+    @Override
+    public void componentClosed() {
+        result.removeLookupListener(this);
+        result = null;
+    }
+
+    @Override
+    public void resultChanged(LookupEvent lookupEvent) {
+        setChain(Utilities.actionsGlobalContext().lookup(FilterChain.class));
+    }
+
+    public void setChain(FilterChain chain) {
+        updateComboBoxSelection();
+    }
+
+    private FileObject getFileObject(CustomFilter cf) {
+        FileObject fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID + "/" + cf.getName());
+        if (fo == null) {
+            try {
+                fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID).createData(cf.getName());
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+        }
+        return fo;
+    }
+
+    @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);
+
+        out.writeInt(filterSettings.size());
+        for (FilterSetting f : filterSettings) {
+            out.writeUTF(f.getName());
+
+            out.writeInt(f.getFilterCount());
+            for (Filter filter : f.getFilters()) {
+                CustomFilter cf = (CustomFilter) filter;
+                out.writeUTF(cf.getName());
+            }
+        }
+
+        CustomFilter prev = null;
+        for (Filter f : this.sequence.getFilters()) {
+            CustomFilter cf = (CustomFilter) f;
+            FileObject fo = getFileObject(cf);
+            if (getFilterChain().containsFilter(cf)) {
+                fo.setAttribute(ENABLED_ID, true);
+            } else {
+                fo.setAttribute(ENABLED_ID, false);
+            }
+
+            if (prev == null) {
+                fo.setAttribute(AFTER_ID, null);
+            } else {
+                fo.setAttribute(AFTER_ID, prev.getName());
+            }
+
+            prev = cf;
+        }
+    }
+
+    public CustomFilter findFilter(String name) {
+        for (Filter f : sequence.getFilters()) {
+
+            CustomFilter cf = (CustomFilter) f;
+            if (cf.getName().equals(name)) {
+                return cf;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        super.readExternal(in);
+
+        int filterSettingsCount = in.readInt();
+        for (int i = 0; i < filterSettingsCount; i++) {
+            String name = in.readUTF();
+            FilterSetting s = new FilterSetting(name);
+            int filterCount = in.readInt();
+            for (int j = 0; j < filterCount; j++) {
+                String filterName = in.readUTF();
+                CustomFilter filter = findFilter(filterName);
+                if (filter != null) {
+                    s.addFilter(filter);
+                }
+            }
+
+            filterSettings.add(s);
+        }
+        updateComboBox();
+    }
+
+    final static class ResolvableHelper implements Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        public Object readResolve() {
+            return FilterTopComponent.getDefault();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponentSettings.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN" "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">
+<settings version="1.0">
+    <module name="com.sun.hotspot.igv.filterwindow" spec="1.0"/>
+    <instanceof class="org.openide.windows.TopComponent"/>
+    <instanceof class="com.sun.hotspot.igv.filterwindow.FilterTopComponent"/>
+    <instance class="com.sun.hotspot.igv.filterwindow.FilterTopComponent" method="getDefault"/>
+</settings>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponentWstcref.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE tc-ref PUBLIC "-//NetBeans//DTD Top Component in Mode Properties 2.0//EN" "http://www.netbeans.org/dtds/tc-ref2_0.dtd">
+<tc-ref version="2.0" >
+    <module name="com.sun.hotspot.igv.filterwindow" spec="1.0"/>
+    <tc-id id="FilterTopComponent"/>
+    <state opened="true"/>
+</tc-ref>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,7 @@
+CTL_FilterAction=Filters
+CTL_MoveFilterUpAction=Move upwards
+CTL_MoveFilterDownAction=Move downwards
+CTL_RemoveFilterAction=Remove
+CTL_RemoveFilterSettingsAction=Remove filter setting
+CTL_SaveFilterSettingsAction=Create filter profile...
+CTL_NewFilterAction=New filter...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/FilterAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,48 @@
+/*
+ * 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.filterwindow.actions;
+
+import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import org.openide.util.NbBundle;
+import org.openide.windows.TopComponent;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class FilterAction extends AbstractAction {
+
+    public FilterAction() {
+        super(NbBundle.getMessage(FilterAction.class, "CTL_FilterAction"));
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent evt) {
+        TopComponent win = FilterTopComponent.findInstance();
+        win.open();
+        win.requestActive();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterDownAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,90 @@
+/*
+ * 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.filterwindow.actions;
+
+import com.sun.hotspot.igv.filter.Filter;
+import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
+import javax.swing.Action;
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+import org.openide.util.actions.CookieAction;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class MoveFilterDownAction extends CookieAction {
+
+    @Override
+    protected void performAction(Node[] activatedNodes) {
+        for (Node n : activatedNodes) {
+            Filter c = n.getLookup().lookup(Filter.class);
+            FilterTopComponent.findInstance().getSequence().moveFilterDown(c);
+        }
+    }
+
+    @Override
+    protected int mode() {
+        return CookieAction.MODE_EXACTLY_ONE;
+    }
+
+    public MoveFilterDownAction() {
+
+        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
+        };
+    }
+
+    @Override
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/filterwindow/images/down.png";
+    }
+
+    @Override
+    protected void initialize() {
+        super.initialize();
+        putValue("noIconInMenu", Boolean.TRUE);
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterUpAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,89 @@
+/*
+ * 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.filterwindow.actions;
+
+import com.sun.hotspot.igv.filter.Filter;
+import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
+import javax.swing.Action;
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+import org.openide.util.actions.CookieAction;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class MoveFilterUpAction extends CookieAction {
+
+    @Override
+    protected void performAction(Node[] activatedNodes) {
+        for (Node n : activatedNodes) {
+            Filter c = n.getLookup().lookup(Filter.class);
+            FilterTopComponent.findInstance().getSequence().moveFilterUp(c);
+        }
+    }
+
+    @Override
+    protected int mode() {
+        return CookieAction.MODE_EXACTLY_ONE;
+    }
+
+    public MoveFilterUpAction() {
+        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
+        };
+    }
+
+    @Override
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/filterwindow/images/up.png";
+    }
+
+    @Override
+    protected void initialize() {
+        super.initialize();
+        putValue("noIconInMenu", Boolean.TRUE);
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/NewFilterAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,71 @@
+/*
+ * 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.filterwindow.actions;
+
+import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
+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 NewFilterAction extends CallableSystemAction {
+
+    public NewFilterAction() {
+        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");
+    }
+
+    @Override
+    protected void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+
+    @Override
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/filterwindow/images/plus.png";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,104 @@
+/*
+ * 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.filterwindow.actions;
+
+import com.sun.hotspot.igv.filter.Filter;
+import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
+import javax.swing.Action;
+import javax.swing.JOptionPane;
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+import org.openide.util.actions.CookieAction;
+import org.openide.windows.WindowManager;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+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 Filters",
+                JOptionPane.YES_NO_CANCEL_OPTION,
+                JOptionPane.QUESTION_MESSAGE,
+                null,
+                options,
+                options[2]);
+
+        if (n == JOptionPane.YES_OPTION) {
+            for (int i = 0; i < activatedNodes.length; i++) {
+                FilterTopComponent.findInstance().removeFilter(activatedNodes[i].getLookup().lookup(Filter.class));
+            }
+        }
+    }
+
+    @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 selected filter");
+    }
+
+    @Override
+    protected Class[] cookieClasses() {
+        return new Class[]{
+            Filter.class
+        };
+    }
+
+    @Override
+    protected void initialize() {
+        super.initialize();
+        putValue("noIconInMenu", Boolean.TRUE);
+    }
+
+    @Override
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/filterwindow/images/minus.png";
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterSettingsAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,71 @@
+/*
+ * 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.filterwindow.actions;
+
+import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
+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 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, "Delete current filter profile");
+    }
+
+    @Override
+    protected void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+
+    @Override
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/filterwindow/images/delete.png";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/SaveFilterSettingsAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,71 @@
+/*
+ * 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.filterwindow.actions;
+
+import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
+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 SaveFilterSettingsAction extends CallableSystemAction {
+
+    @Override
+    public void performAction() {
+        FilterTopComponent.findInstance().addFilterSetting();
+    }
+
+    @Override
+    public String getName() {
+        return NbBundle.getMessage(SaveFilterSettingsAction.class, "CTL_SaveFilterSettingsAction");
+    }
+
+    @Override
+    protected void initialize() {
+        super.initialize();
+    }
+
+    public SaveFilterSettingsAction() {
+        putValue(Action.SHORT_DESCRIPTION, "Save filter configuration as profile...");
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+
+    @Override
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/filterwindow/images/add.png";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/customRightTopWsmode.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mode version="2.1">
+    <name unique="customRightTopMode" />
+    <kind type="view" />
+    <state type="joined" />
+    <constraints>
+        <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"/>
+    <active-tc id="FilterTopComponent"/>
+    <empty-behavior permanent="false"/>
+</mode>
Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/add.png has changed
Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.png has changed
Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.png has changed
Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.png has changed
Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.png has changed
Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/up.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/layer.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,45 @@
+<?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="Edit">
+        <file name="com-sun-hotspot-igv-filterwindow-actions-MoveFilterDownAction.instance">
+            <attr name="position" intvalue="300"/>
+        </file>
+        <file name="com-sun-hotspot-igv-filterwindow-actions-MoveFilterUpAction.instance">
+            <attr name="position" intvalue="400"/>
+        </file>
+        <file name="com-sun-hotspot-igv-filterwindow-actions-RemoveFilterAction.instance">
+            <attr name="position" intvalue="500"/>
+        </file>
+        <file name="com-sun-hotspot-igv-filterwindow-actions-RemoveFilterSettingsAction.instance">
+            <attr name="position" intvalue="600"/>
+        </file>
+        <file name="com-sun-hotspot-igv-filterwindow-actions-SaveFilterSettingsAction.instance">
+            <attr name="position" intvalue="900"/>
+        </file>
+    </folder>
+    
+    <folder name="Actions">
+        <folder name="Window">
+            <file name="com-sun-hotspot-igv-filterwindow-actions-FilterAction.instance"/>
+        </folder>
+    </folder>
+    <folder name="Menu">
+        <folder name="Window">
+            <file name="FilterAction.shadow">
+                <attr name="originalFile" stringvalue="Actions/Window/com-sun-hotspot-igv-filterwindow-actions-FilterAction.instance"/>
+            </file>
+        </folder>
+    </folder>
+    <folder name="Windows2">
+        <folder name="Components">
+            <file name="FilterTopComponent.settings" url="FilterTopComponentSettings.xml"/>
+        </folder>
+        <folder name="Modes">
+            <file name="customRightTopMode.wsmode" url="customRightTopWsmode.xml"/>
+            <folder name="customRightTopMode">
+                <file name="FilterTopComponent.wstcref" url="FilterTopComponentWstcref.xml"/>
+            </folder>
+        </folder>
+    </folder>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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/visualizer/Graal/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -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/visualizer/Graal/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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/visualizer/Graal/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=79002a09
+build.xml.script.CRC32=3534d355
+build.xml.stylesheet.CRC32=a56c6a5b@2.47.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=79002a09
+nbproject/build-impl.xml.script.CRC32=2867f2d5
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,37 @@
+<?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.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/visualizer/Graal/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=GraalCompilerSupport
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.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 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<Figure> figuresToRemove = new HashSet<>();
+        Set<Connection> connectionsToRemove = new HashSet<>();
+        for (Figure f : d.getFigures()) {
+            final String prop = f.getProperties().get("probability");
+            
+            if (prop == null) {
+                figuresToRemove.add(f);
+            }
+        }
+        d.removeAllFigures(figuresToRemove);
+        
+        for (Figure f : d.getFigures()) {
+            Properties p = f.getProperties();
+            int predCount = Integer.parseInt(p.get("predecessorCount"));
+            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();
+            System.out.println("rm " + c);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalColoringFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.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/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.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.List;
+
+/**
+ * Filter that colors usage and successor edges differently.
+ * 
+ * @author Peter Hofer
+ */
+public class GraalEdgeColorFilter extends AbstractFilter {
+
+    private Color successorColor = Color.BLUE;
+    private Color usageColor = Color.RED;
+    private Color memoryColor = Color.GREEN;
+
+    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) {
+            Properties p = f.getProperties();
+            int predCount;
+            if (p.get("predecessorCount") != null) {
+                predCount = Integer.parseInt(p.get("predecessorCount"));
+            } else {
+                predCount = 0;
+            }
+            for (InputSlot is : f.getInputSlots()) {
+                Color color;
+                ConnectionStyle style = ConnectionStyle.NORMAL;
+                if (is.getPosition() < predCount) {
+                    color = successorColor;
+                    style = ConnectionStyle.BOLD;
+                } else {
+                    color = usageColor;
+                }
+
+                is.setColor(color);
+                for (Connection c : is.getConnections()) {
+                    if (c.getLabel() == null || !c.getLabel().endsWith("#NDF")) {
+                        c.setColor(color);
+                        c.setStyle(style);
+                    } else if ("EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class"))
+                            || "EndNode".equals(c.getOutputSlot().getProperties().get("class"))) {
+                        c.setColor(successorColor);
+                        c.setStyle(ConnectionStyle.BOLD);
+                    }
+                }
+            }
+        }
+    }
+
+    public Color getUsageColor() {
+        return usageColor;
+    }
+
+    public void setUsageColor(Color usageColor) {
+        this.usageColor = usageColor;
+    }
+
+    public void setMemoryColor(Color memoryColor) {
+        this.memoryColor = memoryColor;
+    }
+
+    public Color getMemoryColor() {
+        return memoryColor;
+    }
+
+    public Color getSuccessorColor() {
+        return successorColor;
+    }
+
+    public void setSuccessorColor(Color successorColor) {
+        this.successorColor = successorColor;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/beginend.filter	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,4 @@
+var f = new CombineFilter("Combine Filter");
+f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("class", ".*"), new Properties.RegexpPropertyMatcher("class", "BeginNode"), false, "shortName"));
+f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("class", "EndNode"), new Properties.RegexpPropertyMatcher("class", ".*"), true, "shortName"));
+f.apply(graph);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/callgraph.filter	Wed Feb 08 21:15:00 2012 -0800
@@ -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/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/cfg.filter	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+var f = new com.sun.hotspot.igv.graal.filters.GraalCFGFilter();
+f.apply(graph);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,11 @@
+colorize("name", ".*", white);
+colorize("name", "StartNode|EndNode|LoopBegin|LoopEnd|Return", orange);
+colorize("name", "Phi:.*", magenta);
+colorize("name", "FrameState@.*", new java.awt.Color(0.5, 0.8, 1.0));
+colorize("name", "If", pink);
+colorize("name", "const.*", new java.awt.Color(0.7, 0.7, 0.7));
+colorize("name", "Local", new java.awt.Color(0.85, 0.85, 0.85));
+colorize("name", "\\+|-|\\*|/", cyan);
+colorize("name", "Comp .*", yellow);
+
+colorize("notInOwnBlock", "true", red);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/edgeColor.filter	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,4 @@
+var f = new com.sun.hotspot.igv.graal.filters.GraalEdgeColorFilter();
+f.setUsageColor(blue);
+f.setSuccessorColor(red);
+f.apply(graph);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/framestatelocks.filter	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+colorize("class", "FrameState", red);
+colorize("locks", "", gray);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/noframestate.filter	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+remove("class", "FrameState");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/probability.filter	Wed Feb 08 21:15:00 2012 -0800
@@ -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/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/slots.filter	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+removeUnconnectedSlots(true, true);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/layer.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,41 @@
+<?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="Graal Coloring" url="filters/color.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Graal Edge Coloring" url="filters/edgeColor.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Graal Remove Unconnected Slots" url="filters/slots.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Graal Probability" url="filters/probability.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Graal Reduce Begin-End" url="filters/beginend.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Graal Remove FrameState" url="filters/noframestate.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Graal Mark FrameState With Lock" url="filters/framestatelocks.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Graal Call Analysis" url="filters/callgraph.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Graal CFG-only" url="filters/cfg.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+    </folder>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.graph" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.graph.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.graph
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/graph/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.graph-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=b2bc2f02
+build.xml.script.CRC32=486d5dab
+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=b2bc2f02
+nbproject/build-impl.xml.script.CRC32=17fa0f49
+nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,32 @@
+<?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.graph</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.layout</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>
+                <package>com.sun.hotspot.igv.graph.services</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/AndSelector.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,55 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class AndSelector implements Selector {
+
+    private Selector selector1;
+    private Selector selector2;
+
+    public AndSelector(Selector s1, Selector s2) {
+        this.selector1 = s1;
+        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<>();
+        for (Figure f : l2) {
+            if (l1.contains(f)) {
+                result.add(f);
+            }
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Graph
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,154 @@
+/*
+ * 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.Source;
+import com.sun.hotspot.igv.layout.Link;
+import com.sun.hotspot.igv.layout.Port;
+import java.awt.Color;
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 
+ * @author Thomas Wuerthinger
+ */
+public class Connection implements Source.Provider, Link {
+
+    @Override
+    public boolean isVIP() {
+        return style == ConnectionStyle.BOLD;
+    }
+
+    public enum ConnectionStyle {
+
+        NORMAL,
+        DASHED,
+        BOLD
+    }
+    private InputSlot inputSlot;
+    private OutputSlot outputSlot;
+    private Source source;
+    private Color color;
+    private ConnectionStyle style;
+    private List<Point> controlPoints;
+    private String label;
+
+    protected Connection(InputSlot inputSlot, OutputSlot outputSlot, String label) {
+        this.inputSlot = inputSlot;
+        this.outputSlot = outputSlot;
+        this.label = label;
+        this.inputSlot.connections.add(this);
+        this.outputSlot.connections.add(this);
+        controlPoints = new ArrayList<>();
+        Figure sourceFigure = this.outputSlot.getFigure();
+        Figure destFigure = this.inputSlot.getFigure();
+        sourceFigure.addSuccessor(destFigure);
+        destFigure.addPredecessor(sourceFigure);
+        source = new Source();
+
+        this.color = Color.BLACK;
+        this.style = ConnectionStyle.NORMAL;
+    }
+
+    public InputSlot getInputSlot() {
+        return inputSlot;
+    }
+
+    public OutputSlot getOutputSlot() {
+        return outputSlot;
+    }
+
+    public Color getColor() {
+        return color;
+    }
+
+    public ConnectionStyle getStyle() {
+        return style;
+    }
+
+    public void setColor(Color c) {
+        color = c;
+    }
+
+    public void setStyle(ConnectionStyle s) {
+        style = s;
+    }
+
+    @Override
+    public Source getSource() {
+        return source;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void remove() {
+        inputSlot.getFigure().removePredecessor(outputSlot.getFigure());
+        inputSlot.connections.remove(this);
+        outputSlot.getFigure().removeSuccessor(inputSlot.getFigure());
+        outputSlot.connections.remove(this);
+    }
+    
+    public String getToolTipText() {
+        StringBuilder builder = new StringBuilder();
+        if (label != null) {
+            builder.append(label).append(": from ");
+        } else {
+            builder.append("From ");
+        }
+        builder.append(getOutputSlot().getFigure());
+        builder.append(" to ");
+        builder.append(getInputSlot().getFigure());
+        return builder.toString();
+    }
+
+    @Override
+    public String toString() {
+        return "Connection('" + label + "', " + getFrom().getVertex() + " to " + getTo().getVertex() + ")";
+    }
+
+    @Override
+    public Port getFrom() {
+        return outputSlot;
+    }
+
+    @Override
+    public Port getTo() {
+        return inputSlot;
+    }
+
+    @Override
+    public List<Point> getControlPoints() {
+        return controlPoints;
+    }
+
+    @Override
+    public void setControlPoints(List<Point> list) {
+        controlPoints = list;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,283 @@
+/*
+ * 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.InputEdge;
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher;
+import java.awt.Font;
+import java.util.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Diagram {
+
+    private List<Figure> figures;
+    private InputGraph graph;
+    private int curId;
+    private String nodeText;
+    private Font font;
+    private Font slotFont;
+
+    public Font getFont() {
+        return font;
+    }
+
+    public Font getSlotFont() {
+        return slotFont;
+    }
+    
+    private Diagram() {
+        figures = new ArrayList<>();
+        this.nodeText = "";
+        this.font = new Font("Arial", Font.PLAIN, 13);
+        this.slotFont = new Font("Arial", Font.PLAIN, 10);
+    }
+
+    public String getNodeText() {
+        return nodeText;
+    }
+
+    public Diagram getNext() {
+        return Diagram.createDiagram(graph.getNext(), nodeText);
+    }
+
+    public Diagram getPrev() {
+        return Diagram.createDiagram(graph.getPrev(), nodeText);
+    }
+
+    public List<Figure> getFigures() {
+        return Collections.unmodifiableList(figures);
+    }
+
+    public Figure createFigure() {
+        Figure f = new Figure(this, curId);
+        curId++;
+        this.figures.add(f);
+        return f;
+    }
+
+    public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label) {
+        assert inputSlot.getFigure().getDiagram() == this;
+        assert outputSlot.getFigure().getDiagram() == this;
+        return new Connection(inputSlot, outputSlot, label);
+    }
+    
+    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) {
+        if (graph == null) {
+            return null;
+        }
+
+        Diagram d = new Diagram();
+        d.graph = graph;
+        d.nodeText = nodeText;
+
+        Collection<InputNode> nodes = graph.getNodes();
+        Hashtable<Integer, Figure> figureHash = new Hashtable<>();
+        for (InputNode n : nodes) {
+            Figure f = d.createFigure();
+            f.getSource().addSourceNode(n);
+            f.getProperties().add(n.getProperties());
+            figureHash.put(n.getId(), f);
+        }
+
+        for (InputEdge e : graph.getEdges()) {
+
+            int from = e.getFrom();
+            int to = e.getTo();
+            Figure fromFigure = figureHash.get(from);
+            Figure toFigure = figureHash.get(to);
+            assert fromFigure != null && toFigure != null;
+            
+            if(fromFigure == null || toFigure == null) continue;
+
+            int fromIndex = e.getFromIndex();
+            while (fromFigure.getOutputSlots().size() <= fromIndex) {
+                fromFigure.createOutputSlot();
+            }
+            OutputSlot outputSlot = fromFigure.getOutputSlots().get(fromIndex);
+
+            int toIndex = e.getToIndex();
+            while (toFigure.getInputSlots().size() <= toIndex) {
+                toFigure.createInputSlot();
+            }
+            InputSlot inputSlot = toFigure.getInputSlots().get(toIndex);
+
+            Connection c = d.createConnection(inputSlot, outputSlot, e.getLabel());
+
+            if (e.getState() == InputEdge.State.NEW) {
+                c.setStyle(Connection.ConnectionStyle.BOLD);
+            } else if (e.getState() == InputEdge.State.DELETED) {
+                c.setStyle(Connection.ConnectionStyle.DASHED);
+            }
+        }
+
+
+        return d;
+    }
+
+    public void removeAllFigures(Set<Figure> figuresToRemove) {
+        for (Figure f : figuresToRemove) {
+            freeFigure(f);
+        }
+
+        ArrayList<Figure> newFigures = new ArrayList<>();
+        for (Figure f : this.figures) {
+            if (!figuresToRemove.contains(f)) {
+                newFigures.add(f);
+            }
+        }
+        figures = newFigures;
+    }
+
+    private void freeFigure(Figure succ) {
+
+        List<InputSlot> inputSlots = new ArrayList<>(succ.getInputSlots());
+        for (InputSlot s : inputSlots) {
+            succ.removeInputSlot(s);
+        }
+
+        List<OutputSlot> outputSlots = new ArrayList<>(succ.getOutputSlots());
+        for (OutputSlot s : outputSlots) {
+            succ.removeOutputSlot(s);
+        }
+
+        assert succ.getInputSlots().size() == 0;
+        assert succ.getOutputSlots().size() == 0;
+        assert succ.getPredecessors().size() == 0;
+        assert succ.getSuccessors().size() == 0;
+
+    }
+
+    public void removeFigure(Figure succ) {
+
+        assert this.figures.contains(succ);
+        freeFigure(succ);
+        this.figures.remove(succ);
+    }
+
+    public String getName() {
+        return graph.getName();
+    }
+
+    public InputGraph getGraph() {
+        return graph;
+    }
+
+    public Set<Connection> getConnections() {
+
+        Set<Connection> connections = new HashSet<>();
+        for (Figure f : figures) {
+
+            for (InputSlot s : f.getInputSlots()) {
+                connections.addAll(s.getConnections());
+            }
+        }
+
+        return connections;
+    }
+
+    public Figure getRootFigure() {
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(figures);
+        Figure root = selector.selectSingle(new StringPropertyMatcher("name", "Root"));
+        if (root == null) {
+            root = selector.selectSingle(new StringPropertyMatcher("name", "Start"));
+        }
+        if (root == null) {
+            List<Figure> rootFigures = getRootFigures();
+            if (rootFigures.size() > 0) {
+                root = rootFigures.get(0);
+            } else if (figures.size() > 0) {
+                root = figures.get(0);
+            }
+        }
+
+        return root;
+    }
+
+    public void printStatistics() {
+        System.out.println("=============================================================");
+        System.out.println("Diagram statistics");
+
+        List<Figure> tmpFigures = getFigures();
+        Set<Connection> connections = getConnections();
+
+        System.out.println("Number of figures: " + tmpFigures.size());
+        System.out.println("Number of connections: " + connections.size());
+
+        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();
+            }
+        });
+
+        final int COUNT = 10;
+        int z = 0;
+        for (Figure f : figuresSorted) {
+
+            z++;
+            int sum = f.getPredecessors().size() + f.getSuccessors().size();
+            System.out.println("#" + z + ": " + f + ", predCount=" + f.getPredecessors().size() + " succCount=" + f.getSuccessors().size());
+            if (sum < COUNT) {
+                break;
+            }
+
+        }
+
+        System.out.println("=============================================================");
+    }
+
+    public List<Figure> getRootFigures() {
+        ArrayList<Figure> rootFigures = new ArrayList<>();
+        for (Figure f : figures) {
+            if (f.getPredecessors().size() == 0) {
+                rootFigures.add(f);
+            }
+        }
+        return rootFigures;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,355 @@
+/*
+ * 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.InputNode;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Source;
+import com.sun.hotspot.igv.layout.Vertex;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.util.List;
+import java.util.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Figure extends Properties.Entity implements Source.Provider, Vertex {
+
+    public static final int INSET = 12;
+    public static int SLOT_WIDTH = 12;
+    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;
+    private Source source;
+    private Diagram diagram;
+    private Point position;
+    private List<Figure> predecessors;
+    private List<Figure> successors;
+    private Color color;
+    private int id;
+    private String idString;
+    private String[] lines;
+    private int heightCash = -1;
+    private int widthCash = -1;
+
+    public int getHeight() {
+        if (heightCash == -1) {
+            BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+            Graphics g = image.getGraphics();
+            g.setFont(diagram.getFont().deriveFont(Font.BOLD));
+            FontMetrics metrics = g.getFontMetrics();
+            String nodeText = diagram.getNodeText();
+            heightCash = nodeText.split("\n").length * metrics.getHeight() + INSET;
+        }
+        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().deriveFont(Font.BOLD));
+            FontMetrics metrics = g.getFontMetrics();
+            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;
+    }
+
+    protected Figure(Diagram diagram, int id) {
+        this.diagram = diagram;
+        this.source = new Source();
+        inputSlots = new ArrayList<>(5);
+        outputSlots = new ArrayList<>(1);
+        predecessors = new ArrayList<>(6);
+        successors = new ArrayList<>(6);
+        this.id = id;
+        idString = Integer.toString(id);
+
+        this.position = new Point(0, 0);
+        this.color = Color.WHITE;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setColor(Color color) {
+        this.color = color;
+    }
+
+    public Color getColor() {
+        return color;
+    }
+
+    public List<Figure> getPredecessors() {
+        return Collections.unmodifiableList(predecessors);
+    }
+
+    public Set<Figure> getPredecessorSet() {
+        Set<Figure> result = new HashSet<>();
+        for (Figure f : getPredecessors()) {
+            result.add(f);
+        }
+        return Collections.unmodifiableSet(result);
+    }
+
+    public Set<Figure> getSuccessorSet() {
+        Set<Figure> result = new HashSet<>();
+        for (Figure f : getSuccessors()) {
+            result.add(f);
+        }
+        return Collections.unmodifiableSet(result);
+    }
+
+    public List<Figure> getSuccessors() {
+        return Collections.unmodifiableList(successors);
+    }
+
+    protected void addPredecessor(Figure f) {
+        this.predecessors.add(f);
+    }
+
+    protected void addSuccessor(Figure f) {
+        this.successors.add(f);
+    }
+
+    protected void removePredecessor(Figure f) {
+        assert predecessors.contains(f);
+        predecessors.remove(f);
+    }
+
+    protected void removeSuccessor(Figure f) {
+        assert successors.contains(f);
+        successors.remove(f);
+    }
+
+    @Override
+    public void setPosition(Point p) {
+        this.position = p;
+    }
+
+    @Override
+    public Point getPosition() {
+        return position;
+    }
+
+    public Diagram getDiagram() {
+        return diagram;
+    }
+
+    @Override
+    public Source getSource() {
+        return source;
+    }
+
+    public InputSlot createInputSlot() {
+        InputSlot slot = new InputSlot(this, -1);
+        inputSlots.add(slot);
+        return slot;
+    }
+
+    public InputSlot createInputSlot(int index) {
+        InputSlot slot = new InputSlot(this, index);
+        inputSlots.add(slot);
+        Collections.sort(inputSlots, Slot.slotIndexComparator);
+        return slot;
+    }
+
+    public void removeSlot(Slot s) {
+
+        assert inputSlots.contains(s) || outputSlots.contains(s);
+
+        List<Connection> connections = new ArrayList<>(s.getConnections());
+        for (Connection c : connections) {
+            c.remove();
+        }
+
+        if (inputSlots.contains(s)) {
+            inputSlots.remove(s);
+        } else if (outputSlots.contains(s)) {
+            outputSlots.remove(s);
+        }
+    }
+
+    public OutputSlot createOutputSlot() {
+        OutputSlot slot = new OutputSlot(this, -1);
+        outputSlots.add(slot);
+        return slot;
+    }
+
+    public OutputSlot createOutputSlot(int index) {
+        OutputSlot slot = new OutputSlot(this, index);
+        outputSlots.add(slot);
+        Collections.sort(outputSlots, Slot.slotIndexComparator);
+        return slot;
+    }
+
+    public List<InputSlot> getInputSlots() {
+        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);
+    }
+
+    void removeInputSlot(InputSlot s) {
+        s.removeAllConnections();
+        inputSlots.remove(s);
+    }
+
+    void removeOutputSlot(OutputSlot s) {
+        s.removeAllConnections();
+        outputSlots.remove(s);
+    }
+
+    public String[] getLines() {
+        if (lines == null) {
+            updateLines();
+        }
+        return lines;
+    }
+
+    public void updateLines() {
+        String[] strings = diagram.getNodeText().split("\n");
+        String[] result = new String[strings.length];
+
+        for (int i = 0; i < strings.length; i++) {
+            result[i] = resolveString(strings[i], getProperties());
+        }
+
+        lines = result;
+    }
+
+    public static final String resolveString(String string, Properties properties) {
+
+        StringBuilder sb = new StringBuilder();
+        boolean inBrackets = false;
+        StringBuilder curIdent = new StringBuilder();
+
+        for (int i = 0; i < string.length(); i++) {
+            char c = string.charAt(i);
+            if (inBrackets) {
+                if (c == ']') {
+                    String value = properties.get(curIdent.toString());
+                    if (value == null) {
+                        value = "";
+                    }
+                    sb.append(value);
+                    inBrackets = false;
+                } else {
+                    curIdent.append(c);
+                }
+            } else {
+                if (c == '[') {
+                    inBrackets = true;
+                    curIdent = new StringBuilder();
+                } else {
+                    sb.append(c);
+                }
+            }
+        }
+
+        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 - 2 * Figure.OVERLAPPING;
+            
+            
+            return new Dimension(width, height);
+        } else {
+            int width = getWidth() + 2 * Figure.SLOT_WIDTH - 2*Figure.OVERLAPPING;
+            int height = Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1);
+            return new Dimension(width, height);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return idString;
+    }
+
+    @Override
+    public boolean isRoot() {
+  
+        List<InputNode> sourceNodes = source.getSourceNodes();
+        if (sourceNodes.size() > 0 && sourceNodes.get(0).getProperties().get("name") != null) {
+            return source.getSourceNodes().get(0).getProperties().get("name").equals("Root");
+        } 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()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/InputSlot.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,63 @@
+/*
+ * 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 java.awt.Point;
+import java.util.List;
+
+/**
+ * 
+ * @author Thomas Wuerthinger
+ */
+public class InputSlot extends Slot {
+
+    protected InputSlot(Figure figure, int wantedIndex) {
+        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() {
+        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
+    public String toString() {
+        return "InputSlot[figure=" + this.getFigure().toString() + ", position=" + getPosition() + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/InvertSelector.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,54 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InvertSelector implements Selector {
+
+    private Selector selector;
+
+    public InvertSelector(Selector selector) {
+        this.selector = selector;
+    }
+
+    @Override
+    public List<Figure> selected(Diagram d) {
+
+        List<Figure> result = new ArrayList<>();
+        List<Figure> otherResult = selector.selected(d);
+        for (Figure f : d.getFigures()) {
+            if (!otherResult.contains(f)) {
+                result.add(f);
+            }
+        }
+
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/MatcherSelector.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,48 @@
+/*
+ * 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.Properties;
+import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class MatcherSelector implements Selector {
+
+    private PropertyMatcher matcher;
+
+    public MatcherSelector(PropertyMatcher matcher) {
+        this.matcher = matcher;
+    }
+
+    @Override
+    public List<Figure> selected(Diagram d) {
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(d.getFigures());
+        List<Figure> list = selector.selectMultiple(matcher);
+        return list;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/OrSelector.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,57 @@
+/*
+ * 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 java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class OrSelector implements Selector {
+
+    private Selector selector1;
+    private Selector selector2;
+
+    /** Creates a new instance of OrSelector */
+    public OrSelector(Selector s1, Selector s2) {
+        this.selector1 = s1;
+        this.selector2 = s2;
+    }
+
+    @Override
+    public List<Figure> selected(Diagram d) {
+
+        List<Figure> l1 = selector1.selected(d);
+        List<Figure> l2 = selector2.selected(d);
+
+        for (Figure f : l2) {
+            if (!l1.contains(f)) {
+                l1.add(f);
+            }
+        }
+
+        return l1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/OutputSlot.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,64 @@
+/*
+ * 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 java.awt.Point;
+
+/**
+ * 
+ * @author Thomas Wuerthinger
+ */
+public class OutputSlot extends Slot {
+
+    protected OutputSlot(Figure figure, int wantedIndex) {
+        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() {
+        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
+    public String toString() {
+        return "OutputSlot[figure=" + this.getFigure().toString() + ", position=" + getPosition() + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/PredecessorSelector.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,60 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class PredecessorSelector implements Selector {
+
+    private Selector innerSelector;
+
+    public PredecessorSelector(Selector innerSelector) {
+        this.innerSelector = innerSelector;
+    }
+
+    @Override
+    public List<Figure> selected(Diagram d) {
+        List<Figure> inner = innerSelector.selected(d);
+        List<Figure> result = new ArrayList<>();
+        for (Figure f : d.getFigures()) {
+            boolean saved = false;
+            for (Figure f2 : f.getSuccessors()) {
+                if (inner.contains(f2)) {
+                    saved = true;
+                }
+            }
+
+            if (saved) {
+                result.add(f);
+            }
+        }
+
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Selector.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,35 @@
+/*
+ * 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 java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface Selector {
+
+    List<Figure> selected(Diagram d);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,195 @@
+/*
+ * 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.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;
+
+/**
+ * 
+ * @author Thomas Wuerthinger
+ */
+public abstract class Slot implements Port, Source.Provider, Properties.Provider {
+
+	private int wantedIndex;
+	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<>(2);
+		source = new Source();
+		this.wantedIndex = wantedIndex;
+		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 getText() {
+		return text;
+	}
+
+	public void setShortName(String s) {
+		assert s != null;
+//        assert s.length() <= 2;
+		this.shortName = s;
+
+	}
+
+	public String getShortName() {
+		return shortName;
+	}
+
+	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 setText(String s) {
+		if (s == null) {
+			s = "";
+		}
+		this.text = s;
+	}
+
+	public Figure getFigure() {
+		assert figure != null;
+		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<>(this.connections);
+		for (Connection c : connectionsCopy) {
+			c.remove();
+		}
+	}
+
+    @Override
+	public Vertex getVertex() {
+		return figure;
+	}
+
+	public abstract int getPosition();
+
+	public abstract void setPosition(int position);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/SuccessorSelector.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,60 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class SuccessorSelector implements Selector {
+
+    private Selector innerSelector;
+
+    public SuccessorSelector(Selector innerSelector) {
+        this.innerSelector = innerSelector;
+    }
+
+    @Override
+    public List<Figure> selected(Diagram d) {
+        List<Figure> inner = innerSelector.selected(d);
+        List<Figure> result = new ArrayList<>();
+        for (Figure f : d.getFigures()) {
+            boolean saved = false;
+            for (Figure f2 : f.getPredecessors()) {
+                if (inner.contains(f2)) {
+                    saved = true;
+                }
+            }
+
+            if (saved) {
+                result.add(f);
+            }
+        }
+
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/services/DiagramProvider.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,38 @@
+/*
+ * 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.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();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.hierarchicallayout" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.hierarchicallayout.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.hierarchicallayout
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/hierarchicallayout/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.hierarchicallayout-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=de087df9
+build.xml.script.CRC32=98977c36
+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=de087df9
+nbproject/build-impl.xml.script.CRC32=0d734625
+nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.hierarchicallayout</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <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>
+            </module-dependencies>
+            <public-packages>
+                <package>com.sun.hotspot.igv.hierarchicallayout</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=HierarchicalLayout
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Edge.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,90 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Edge<N, E> {
+
+    private E data;
+    private Node<N, E> source;
+    private Node<N, E> dest;
+
+    protected Edge(Graph<N, E> graph, Node<N, E> source, Node<N, E> dest, E data) {
+        setData(data);
+        this.source = source;
+        this.dest = dest;
+        assert source != null;
+        assert dest != null;
+        assert source.getGraph() == dest.getGraph();
+        assert source.getGraph() != null;
+        assert dest.getGraph() != null;
+    }
+
+    public Node<N, E> getSource() {
+        return source;
+    }
+
+    public Node<N, E> getDest() {
+        return dest;
+    }
+
+    public E getData() {
+        return data;
+    }
+
+    public void setData(E e) {
+        data = e;
+    }
+
+    public void remove() {
+        source.getGraph().removeEdge(this, null);
+    }
+
+    public boolean isSelfLoop() {
+        return source == dest;
+    }
+
+    public void reverse() {
+
+        // Remove from current source / dest
+        source.removeOutEdge(this);
+        dest.removeInEdge(this);
+
+        Node<N, E> tmp = source;
+        source = dest;
+        dest = tmp;
+
+        // Add to new source / dest
+        source.addOutEdge(this);
+        dest.addInEdge(this);
+    }
+
+    @Override
+    public String toString() {
+        return "Edge (" + source + " -- " + dest + "): " + data;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,292 @@
+/*
+ * 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.util.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Graph<N, E> {
+
+    private HashMap<Object, Node<N, E>> nodes;
+    private HashMap<Object, Edge<N, E>> edges;
+    private List<Node<N, E>> nodeList;
+
+    public Graph() {
+        nodes = new HashMap<>();
+        edges = new HashMap<>();
+        nodeList = new ArrayList<>();
+    }
+
+    public Node<N, E> createNode(N data, Object key) {
+        Node<N, E> n = new Node<>(this, data);
+        assert key == null || !nodes.containsKey(key);
+        if (key != null) {
+            nodes.put(key, n);
+        }
+        nodeList.add(n);
+        return n;
+    }
+
+    public Edge<N, E> createEdge(Node<N, E> source, Node<N, E> dest, E data, Object key) {
+        Edge<N, E> e = new Edge<>(this, source, dest, data);
+        source.addOutEdge(e);
+        dest.addInEdge(e);
+        if (key != null) {
+            edges.put(key, e);
+        }
+        return e;
+    }
+
+    public Node<N, E> getNode(Object key) {
+        return nodes.get(key);
+    }
+
+    public Edge<N, E> getEdge(Object key) {
+        return edges.get(key);
+    }
+
+    public Collection<Edge<N, E>> getEdges() {
+        return Collections.unmodifiableCollection(edges.values());
+    }
+
+    public Collection<Node<N, E>> getNodes() {
+        return Collections.unmodifiableList(nodeList);
+    }
+
+    public void removeEdge(Edge<N, E> e, Object key) {
+        assert key == null || edges.containsKey(key);
+        if (key != null) {
+            edges.remove(key);
+        }
+        e.getSource().removeOutEdge(e);
+        e.getDest().removeInEdge(e);
+    }
+
+    public class DFSTraversalVisitor {
+
+        public void visitNode(Node<N, E> n) {
+        }
+
+        public boolean visitEdge(Edge<N, E> e, boolean backEdge) {
+            return true;
+        }
+    }
+
+    public class BFSTraversalVisitor {
+
+        public void visitNode(Node<N, E> n, int depth) {
+        }
+    }
+
+    public List<Node<N, E>> getNodesWithInDegree(int x) {
+        return getNodesWithInDegree(x, true);
+    }
+
+    public List<Node<N, E>> getNodesWithInDegree(int x, boolean countSelfLoops) {
+
+        List<Node<N, E>> result = new ArrayList<>();
+        for (Node<N, E> n : getNodes()) {
+            if (n.getInDegree(countSelfLoops) == x) {
+                result.add(n);
+            }
+        }
+
+        return result;
+
+    }
+
+    private void markReachable(Node<N, E> startingNode) {
+        ArrayList<Node<N, E>> arr = new ArrayList<>();
+        arr.add(startingNode);
+        for (Node<N, E> n : getNodes()) {
+            n.setReachable(false);
+        }
+        traverseDFS(arr, new DFSTraversalVisitor() {
+
+            @Override
+            public void visitNode(Node<N, E> n) {
+                n.setReachable(true);
+            }
+        });
+    }
+
+    public void traverseBFS(Node<N, E> startingNode, BFSTraversalVisitor tv, boolean longestPath) {
+
+        if (longestPath) {
+            markReachable(startingNode);
+        }
+
+        for (Node<N, E> n : getNodes()) {
+            n.setVisited(false);
+            n.setActive(false);
+        }
+
+        Queue<Node<N, E>> queue = new LinkedList<>();
+        queue.add(startingNode);
+        startingNode.setVisited(true);
+        int layer = 0;
+        Node<N, E> lastOfLayer = startingNode;
+        Node<N, E> lastAdded = null;
+
+        while (!queue.isEmpty()) {
+
+            Node<N, E> current = queue.poll();
+            tv.visitNode(current, layer);
+            current.setActive(false);
+
+
+            for (Edge<N, E> e : current.getOutEdges()) {
+                if (!e.getDest().isVisited()) {
+
+                    boolean allow = true;
+                    if (longestPath) {
+                        for (Node<N, E> pred : e.getDest().getPredecessors()) {
+                            if ((!pred.isVisited() || pred.isActive()) && pred.isReachable()) {
+                                allow = false;
+                                break;
+                            }
+                        }
+                    }
+
+                    if (allow) {
+                        queue.offer(e.getDest());
+                        lastAdded = e.getDest();
+                        e.getDest().setVisited(true);
+                        e.getDest().setActive(true);
+                    }
+                }
+            }
+
+            if (current == lastOfLayer && !queue.isEmpty()) {
+                lastOfLayer = lastAdded;
+                layer++;
+            }
+        }
+    }
+
+    public void traverseDFS(DFSTraversalVisitor tv) {
+        traverseDFS(getNodes(), tv);
+    }
+
+    public void traverseDFS(Collection<Node<N, E>> startingNodes, DFSTraversalVisitor tv) {
+
+        for (Node<N, E> n : getNodes()) {
+            n.setVisited(false);
+            n.setActive(false);
+        }
+
+        boolean result = false;
+        for (Node<N, E> n : startingNodes) {
+            traverse(tv, n);
+        }
+    }
+
+    private void traverse(DFSTraversalVisitor tv, Node<N, E> n) {
+
+        if (!n.isVisited()) {
+            n.setVisited(true);
+            n.setActive(true);
+            tv.visitNode(n);
+
+            for (Edge<N, E> e : n.getOutEdges()) {
+
+                Node<N, E> next = e.getDest();
+                if (next.isActive()) {
+                    tv.visitEdge(e, true);
+                } else {
+                    if (tv.visitEdge(e, false)) {
+                        traverse(tv, next);
+                    }
+                }
+            }
+
+            n.setActive(false);
+        }
+
+    }
+
+    public boolean hasCycles() {
+
+        for (Node<N, E> n : getNodes()) {
+            n.setVisited(false);
+            n.setActive(false);
+        }
+
+        boolean result = false;
+        for (Node<N, E> n : getNodes()) {
+            result |= checkCycles(n);
+            if (result) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    private boolean checkCycles(Node<N, E> n) {
+
+        if (n.isActive()) {
+            return true;
+        }
+
+        if (!n.isVisited()) {
+
+            n.setVisited(true);
+            n.setActive(true);
+
+            for (Node<N, E> succ : n.getSuccessors()) {
+                if (checkCycles(succ)) {
+                    return true;
+                }
+            }
+
+            n.setActive(false);
+
+        }
+
+        return false;
+    }
+
+    @Override
+    public String toString() {
+
+        StringBuilder s = new StringBuilder();
+        s.append("Nodes: ");
+        for (Node<N, E> n : getNodes()) {
+            s.append(n.toString());
+            s.append("\n");
+        }
+
+        s.append("Edges: ");
+
+        for (Edge<N, E> e : getEdges()) {
+            s.append(e.toString());
+            s.append("\n");
+        }
+
+        return s.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1749 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.hierarchicallayout;
+
+import com.sun.hotspot.igv.layout.LayoutGraph;
+import com.sun.hotspot.igv.layout.LayoutManager;
+import com.sun.hotspot.igv.layout.Link;
+import com.sun.hotspot.igv.layout.Vertex;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.util.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class HierarchicalLayoutManager implements LayoutManager {
+
+    public static final boolean TRACE = false;
+    public static final boolean CHECK = false;
+    public static final int SWEEP_ITERATIONS = 1;
+    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 MAX_LAYER_LENGTH = -1;
+    public static final int MIN_LAYER_DIFFERENCE = 1;
+    public static final int VIP_BONUS = 10;
+
+    public enum Combine {
+
+        NONE,
+        SAME_INPUTS,
+        SAME_OUTPUTS
+    }
+    // Options
+    private Combine combine;
+    private int dummyWidth;
+    private int dummyHeight;
+    private int xOffset;
+    private int layerOffset;
+    private int maxLayerLength;
+    private int minLayerDifference;
+    // Algorithm global datastructures
+    private Set<Link> reversedLinks;
+    private List<LayoutNode> nodes;
+    private HashMap<Vertex, LayoutNode> vertexToLayoutNode;
+    private HashMap<Link, List<Point>> reversedLinkStartPoints;
+    private HashMap<Link, List<Point>> reversedLinkEndPoints;
+    private HashMap<LayoutEdge, LayoutEdge> bottomEdgeHash;
+    private HashMap<Link, List<Point>> splitStartPoints;
+    private HashMap<Link, List<Point>> splitEndPoints;
+    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;
+
+    private class LayoutNode {
+
+        public int x;
+        public int y;
+        public int width;
+        public int height;
+        public int layer = -1;
+        public int xOffset;
+        public int yOffset;
+        public int bottomYOffset;
+        public Vertex vertex; // Only used for non-dummy nodes, otherwise null
+
+        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
+        public String toString() {
+            return "Node " + vertex;
+        }
+    }
+
+    private class LayoutEdge {
+
+        public LayoutNode from;
+        public LayoutNode to;
+        public int relativeFrom;
+        public int relativeTo;
+        public Link link;
+        public boolean vip;
+    }
+
+    private abstract class AlgorithmPart {
+
+        public void start() {
+            if (CHECK) {
+                preCheck();
+            }
+
+            long start = 0;
+            if (TRACE) {
+                System.out.println("##################################################");
+                System.out.println("Starting part " + this.getClass().getName());
+                start = System.currentTimeMillis();
+            }
+            run();
+            if (TRACE) {
+                System.out.println("Timing for " + this.getClass().getName() + " is " + (System.currentTimeMillis() - start));
+                printStatistics();
+            }
+
+            if (CHECK) {
+                postCheck();
+            }
+        }
+
+        protected abstract void run();
+
+        protected void printStatistics() {
+        }
+
+        protected void postCheck() {
+        }
+
+        protected void preCheck() {
+        }
+    }
+
+    public HierarchicalLayoutManager() {
+        this(Combine.NONE);
+    }
+
+    public HierarchicalLayoutManager(Combine b) {
+        this.combine = b;
+        this.dummyWidth = DUMMY_WIDTH;
+        this.dummyHeight = DUMMY_HEIGHT;
+        this.xOffset = X_OFFSET;
+        this.layerOffset = LAYER_OFFSET;
+        this.maxLayerLength = MAX_LAYER_LENGTH;
+        this.minLayerDifference = MIN_LAYER_DIFFERENCE;
+        this.linksToFollow = new HashSet<>();
+    }
+
+    public int getMaxLayerLength() {
+        return maxLayerLength;
+    }
+
+    public void setMaxLayerLength(int v) {
+        maxLayerLength = v;
+    }
+
+    public void setMinLayerDifference(int v) {
+        minLayerDifference = v;
+    }
+
+    @Override
+    public void doLayout(LayoutGraph graph) {
+        doLayout(graph, new HashSet<Vertex>(), new HashSet<Vertex>(), new HashSet<Link>());
+
+    }
+
+    @Override
+    public void doLayout(LayoutGraph graph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinks) {
+
+        this.importantLinks = importantLinks;
+        this.graph = graph;
+        this.firstLayerHint = firstLayerHint;
+        this.lastLayerHint = lastLayerHint;
+
+        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
+        new BuildDatastructure().start();
+
+        // #############################################################
+        // STEP 2: Reverse edges, handle backedges
+        new ReverseEdges().start();
+
+        for (LayoutNode n : nodes) {
+            ArrayList<LayoutEdge> tmpArr = new ArrayList<>();
+            for (LayoutEdge e : n.succs) {
+                if (importantLinks.contains(e.link)) {
+                    tmpArr.add(e);
+                }
+            }
+
+            for (LayoutEdge e : tmpArr) {
+                //System.out.println("Removed " + e);
+                e.from.succs.remove(e);
+                e.to.preds.remove(e);
+            }
+        }
+
+        // #############################################################
+        // STEP 3: Assign layers
+        new AssignLayers().start();
+
+        // #############################################################
+        // STEP 4: Create dummy nodes
+        new CreateDummyNodes().start();
+
+        // #############################################################
+        // STEP 5: Crossing Reduction
+        new CrossingReduction().start();
+
+        // #############################################################
+        // STEP 7: Assign X coordinates
+        new AssignXCoordinates().start();
+
+        // #############################################################
+        // STEP 6: Assign Y coordinates
+        new AssignYCoordinates().start();
+
+        // #############################################################
+        // STEP 8: Write back to interface
+        new WriteResult().start();
+    }
+
+    private class WriteResult extends AlgorithmPart {
+
+        private int pointCount;
+
+        @Override
+        protected void run() {
+
+            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);
+                vertexPositions.put(v, new Point(n.x + n.xOffset, n.y + n.yOffset));
+            }
+
+            for (LayoutNode n : nodes) {
+
+                for (LayoutEdge e : n.preds) {
+                    if (e.link != null) {
+                        ArrayList<Point> points = new ArrayList<>();
+
+                        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) + e.link.getTo().getRelativePosition().y));
+                        }
+
+                        LayoutNode cur = e.from;
+                        LayoutNode other = e.to;
+                        LayoutEdge curEdge = e;
+                        while (cur.vertex == null && cur.preds.size() != 0) {
+                            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);
+                            }
+                            points.add(new Point(cur.x + cur.width / 2, cur.y + cur.height));
+                            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);
+                            }
+                            points.add(new Point(cur.x + cur.width / 2, cur.y));
+                            assert cur.preds.size() == 1;
+                            curEdge = cur.preds.get(0);
+                            cur = curEdge.from;
+                        }
+
+                        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) + (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)) {
+                                for (Point p1 : reversedLinkEndPoints.get(e.link)) {
+                                    points.add(new Point(p1.x + e.to.x, p1.y + e.to.y));
+                                }
+                            }
+
+                            if (splitStartPoints.containsKey(e.link)) {
+                                points.add(0, null);
+                                points.addAll(0, splitStartPoints.get(e.link));
+
+                                //checkPoints(points);
+                                if (reversedLinks.contains(e.link)) {
+                                    Collections.reverse(points);
+                                }
+                                assert !linkPositions.containsKey(e.link);
+                                linkPositions.put(e.link, points);
+                            } else {
+                                splitEndPoints.put(e.link, points);
+                            }
+
+                        } else {
+                            if (reversedLinks.contains(e.link)) {
+                                Collections.reverse(points);
+                            }
+                            if (reversedLinkStartPoints.containsKey(e.link)) {
+                                for (Point p1 : reversedLinkStartPoints.get(e.link)) {
+                                    points.add(new Point(p1.x + cur.x, p1.y + cur.y));
+                                }
+                            }
+
+                            if (reversedLinkEndPoints.containsKey(e.link)) {
+                                for (Point p1 : reversedLinkEndPoints.get(e.link)) {
+                                    points.add(0, new Point(p1.x + other.x, p1.y + other.y));
+                                }
+                            }
+
+                            assert !linkPositions.containsKey(e.link);
+                            linkPositions.put(e.link, points);
+                        }
+                        pointCount += points.size();
+
+                        // No longer needed!
+                        e.link = null;
+                    }
+                }
+
+                for (LayoutEdge e : n.succs) {
+                    if (e.link != null) {
+                        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) + e.link.getFrom().getRelativePosition().y));
+                        }
+
+                        LayoutNode cur = e.to;
+                        LayoutNode other = e.from;
+                        LayoutEdge curEdge = e;
+                        while (cur.vertex == null && cur.succs.size() != 0) {
+                            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);
+                            }
+                            points.add(new Point(cur.x + cur.width / 2, cur.y));
+                            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);
+                            }
+                            points.add(new Point(cur.x + cur.width / 2, cur.y + cur.height));
+                            if (cur.succs.size() == 0) {
+                                break;
+                            }
+                            assert cur.succs.size() == 1;
+                            curEdge = cur.succs.get(0);
+                            cur = curEdge.to;
+                        }
+
+
+                        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) + ((curEdge.link == null) ? 0 : curEdge.link.getTo().getRelativePosition().y)));
+                        }
+
+
+                        if (cur.succs.size() == 0 && 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));
+                                }
+                            }
+
+                            if (splitEndPoints.containsKey(e.link)) {
+                                points.add(null);
+                                points.addAll(splitEndPoints.get(e.link));
+
+                                //checkPoints(points);
+                                if (reversedLinks.contains(e.link)) {
+                                    Collections.reverse(points);
+                                }
+                                assert !linkPositions.containsKey(e.link);
+                                linkPositions.put(e.link, points);
+                            } else {
+                                splitStartPoints.put(e.link, points);
+                            }
+                        } else {
+
+                            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));
+                                }
+                            }
+                            if (reversedLinkEndPoints.containsKey(e.link)) {
+                                for (Point p1 : reversedLinkEndPoints.get(e.link)) {
+                                    points.add(new Point(p1.x + cur.x, p1.y + cur.y));
+                                }
+                            }
+                            if (reversedLinks.contains(e.link)) {
+                                Collections.reverse(points);
+                            }
+                            //checkPoints(points);
+                            assert !linkPositions.containsKey(e.link);
+                            linkPositions.put(e.link, points);
+                        }
+
+                        pointCount += points.size();
+                        e.link = null;
+                    }
+                }
+            }
+
+            int minX = Integer.MAX_VALUE;
+            int minY = Integer.MAX_VALUE;
+            for (Vertex v : vertexPositions.keySet()) {
+                Point p = vertexPositions.get(v);
+                minX = Math.min(minX, p.x);
+                minY = Math.min(minY, p.y);
+            }
+
+            for (Link l : linkPositions.keySet()) {
+                List<Point> points = linkPositions.get(l);
+                for (Point p : points) {
+                    if (p != null) {
+                        minX = Math.min(minX, p.x);
+                        minY = Math.min(minY, p.y);
+                    }
+                }
+
+            }
+
+            for (Vertex v : vertexPositions.keySet()) {
+                Point p = vertexPositions.get(v);
+                p.x -= minX;
+                p.y -= minY;
+                v.setPosition(p);
+            }
+
+            for (Link l : linkPositions.keySet()) {
+                List<Point> points = linkPositions.get(l);
+                for (Point p : points) {
+                    if (p != null) {
+                        p.x -= minX;
+                        p.y -= minY;
+                    }
+                }
+                l.setControlPoints(points);
+
+            }
+        }
+
+        @Override
+        protected void printStatistics() {
+            System.out.println("Number of nodes: " + nodes.size());
+            int edgeCount = 0;
+            for (LayoutNode n : nodes) {
+                edgeCount += n.succs.size();
+            }
+            System.out.println("Number of edges: " + edgeCount);
+            System.out.println("Number of points: " + pointCount);
+        }
+    }
+
+    private static class Segment {
+
+        public float d;
+        public int orderNumber = -1;
+        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;
+        }
+    };
+
+    private static class Region {
+
+        public float d;
+        public int minOrderNumber;
+        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) {
+            if (n1.vertex == null) {
+                if (n2.vertex == null) {
+                    return 0;
+                }
+                return -1;
+            }
+            if (n2.vertex == null) {
+                return 1;
+            }
+            return n1.preds.size() - n2.preds.size();
+        }
+    };
+    private static final Comparator<LayoutNode> nodeProcessingUpComparator = new Comparator<LayoutNode>() {
+
+        @Override
+        public int compare(LayoutNode n1, LayoutNode n2) {
+            if (n1.vertex == null) {
+                if (n2.vertex == null) {
+                    return 0;
+                }
+                return -1;
+            }
+            if (n2.vertex == null) {
+                return 1;
+            }
+            return n1.succs.size() - n2.succs.size();
+        }
+    };
+
+    private class AssignXCoordinates extends AlgorithmPart {
+
+        private ArrayList<Integer>[] space;
+        private ArrayList<LayoutNode>[] downProcessingOrder;
+        private ArrayList<LayoutNode>[] upProcessingOrder;
+
+        private void initialPositions() {
+            for (LayoutNode n : nodes) {
+                n.x = space[n.layer].get(n.pos);
+            }
+        }
+        
+        @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<>();
+                downProcessingOrder[i] = new ArrayList<>();
+                upProcessingOrder[i] = new ArrayList<>();
+
+                int curX = 0;
+                for (LayoutNode n : layers[i]) {
+                    space[i].add(curX);
+                    curX += n.width + xOffset;
+                    downProcessingOrder[i].add(n);
+                    upProcessingOrder[i].add(n);
+                }
+
+                Collections.sort(downProcessingOrder[i], nodeProcessingDownComparator);
+                Collections.sort(upProcessingOrder[i], nodeProcessingUpComparator);
+            }
+
+            initialPositions();
+            for (int i = 0; i < SWEEP_ITERATIONS; i++) {
+                sweepDown();
+                sweepUp();
+            }
+ 
+            sweepDown();
+            //for (int i = 0; i < SWEEP_ITERATIONS; i++) {
+            //    doubleSweep();
+            //}            
+        }
+
+        private int calculateOptimalDown(LayoutNode n) {
+            int size = n.preds.size();
+            if (size == 0) {
+                return n.x;
+            }
+            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;
+                if (e.vip) {
+                    return values[i];
+                }
+            }
+            return median(values);
+        }
+
+        private int calculateOptimalBoth(LayoutNode n) {
+            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) {
+                values[i] = e.from.x + e.relativeFrom - e.relativeTo;
+                i++;
+            }
+
+            for (LayoutEdge e : n.succs) {
+                values[i] = e.to.x + e.relativeTo - e.relativeFrom;
+                i++;
+            }
+
+            return median(values);
+        }
+
+        private int calculateOptimalUp(LayoutNode n) {
+            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 {
+                return values[values.length / 2];
+            }
+        }
+
+        private void sweepUp() {
+            for (int i = layers.length - 1; i >= 0; i--) {
+                NodeRow r = new NodeRow(space[i]);
+                for (LayoutNode n : upProcessingOrder[i]) {
+                    int optimal = calculateOptimalUp(n);
+                    r.insert(n, optimal);
+                }
+            }
+        }
+
+        private void doubleSweep() {
+            for (int i = layers.length - 2; i >= 0; i--) {
+                NodeRow r = new NodeRow(space[i]);
+                for (LayoutNode n : upProcessingOrder[i]) {
+                    int optimal = calculateOptimalBoth(n);
+                    r.insert(n, optimal);
+                }
+            }
+        }
+
+        private void sweepDown() {
+            for (int i = 1; i < layers.length; i++) {
+                NodeRow r = new NodeRow(space[i]);
+                for (LayoutNode n : downProcessingOrder[i]) {
+                    int optimal = calculateOptimalDown(n);
+                    r.insert(n, optimal);
+                }
+            }
+        }
+    }
+
+    private static class NodeRow {
+
+        private TreeSet<LayoutNode> treeSet;
+        private ArrayList<Integer> space;
+
+        public NodeRow(ArrayList<Integer> space) {
+            treeSet = new TreeSet<>(nodePositionComparator);
+            this.space = space;
+        }
+
+        public int offset(LayoutNode n1, LayoutNode n2) {
+            int v1 = space.get(n1.pos) + n1.width;
+            int v2 = space.get(n2.pos);
+            return v2 - v1;
+        }
+
+        public void insert(LayoutNode n, int pos) {
+
+            SortedSet<LayoutNode> headSet = treeSet.headSet(n);
+
+            LayoutNode leftNeighbor = null;
+            int minX = Integer.MIN_VALUE;
+            if (!headSet.isEmpty()) {
+                leftNeighbor = headSet.last();
+                minX = leftNeighbor.x + leftNeighbor.width + offset(leftNeighbor, n);
+            }
+
+            if (pos < minX) {
+                n.x = minX;
+            } else {
+
+                LayoutNode rightNeighbor = null;
+                SortedSet<LayoutNode> tailSet = treeSet.tailSet(n);
+                int maxX = Integer.MAX_VALUE;
+                if (!tailSet.isEmpty()) {
+                    rightNeighbor = tailSet.first();
+                    maxX = rightNeighbor.x - offset(n, rightNeighbor) - n.width;
+                }
+
+                if (pos > maxX) {
+                    n.x = maxX;
+                } else {
+                    n.x = pos;
+                }
+
+                assert minX <= maxX;
+            }
+
+            treeSet.add(n);
+        }
+    }
+    private static Comparator<LayoutNode> crossingNodeComparator = new Comparator<LayoutNode>() {
+
+        @Override
+        public int compare(LayoutNode n1, LayoutNode n2) {
+            return n1.crossingNumber - n2.crossingNumber;
+        }
+    };
+
+    private class CrossingReduction extends AlgorithmPart {
+
+        @Override
+        public void preCheck() {
+            for (LayoutNode n : nodes) {
+                assert n.layer < layerCount;
+            }
+        }
+        
+        @SuppressWarnings("unchecked")
+        private void createLayers() {
+            layers = new List[layerCount];
+
+            for (int i = 0; i < layerCount; i++) {
+                layers[i] = new ArrayList<>();
+            }
+        }
+
+        @Override
+        protected void run() {
+            createLayers();
+
+            // Generate initial ordering
+            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) {
+                    layers[n.layer].add(n);
+                    visited.add(n);
+                }
+            }
+
+            for (int i = 0; i < layers.length - 1; i++) {
+                for (LayoutNode n : layers[i]) {
+                    for (LayoutEdge e : n.succs) {
+                        if (!visited.contains(e.to)) {
+                            visited.add(e.to);
+                            layers[i + 1].add(e.to);
+                        }
+                    }
+                }
+            }
+
+
+            updatePositions();
+
+            initX();
+
+            // Optimize
+            for (int i = 0; i < CROSSING_ITERATIONS; i++) {
+                downSweep();
+                upSweep();
+            }
+            if (reversedLinks.isEmpty()) {
+                // This graph seems to be a tree or forest.
+                // A final down-sweep will usually give us a better layout.
+                downSweep();
+            }
+        }
+
+        private void initX() {
+
+            for (int i = 0; i < layers.length; i++) {
+                updateXOfLayer(i);
+            }
+        }
+
+        private void updateXOfLayer(int index) {
+            int x = 0;
+
+            for (LayoutNode n : layers[index]) {
+                n.x = x;
+                x += n.width + X_OFFSET;
+            }
+        }
+
+        private void updatePositions() {
+
+            for (int i = 0; i < layers.length; i++) {
+                int z = 0;
+                for (LayoutNode n : layers[i]) {
+                    n.pos = z;
+                    z++;
+                }
+            }
+        }
+
+        private void downSweep() {
+
+            // Downsweep
+            for (int i = 1; i < layerCount; i++) {
+
+                for (LayoutNode n : layers[i]) {
+                    n.crossingNumber = 0;
+                }
+
+                for (LayoutNode n : layers[i]) {
+
+                    int sum = 0;
+                    int count = 0;
+                    for (LayoutEdge e : n.preds) {
+                        int cur = e.from.x + e.relativeFrom;
+                        int factor = 1;
+                        if (e.vip) {
+                            factor = VIP_BONUS;
+                        }
+                        sum += cur*factor;
+                        count+=factor;
+                    }
+
+                    if (count > 0) {
+                        sum /= count;
+                        n.crossingNumber = sum;
+                    }
+                }
+
+
+                updateCrossingNumbers(i, true);
+                Collections.sort(layers[i], crossingNodeComparator);
+                updateXOfLayer(i);
+
+                int z = 0;
+                for (LayoutNode n : layers[i]) {
+                    n.pos = z;
+                    z++;
+                }
+            }
+        }
+
+        private void updateCrossingNumbers(int index, boolean down) {
+            for (int i = 0; i < layers[index].size(); i++) {
+                LayoutNode n = layers[index].get(i);
+                LayoutNode prev = null;
+                if (i > 0) {
+                    prev = layers[index].get(i - 1);
+                }
+                LayoutNode next = null;
+                if (i < layers[index].size() - 1) {
+                    next = layers[index].get(i + 1);
+                }
+
+                boolean cond = n.succs.isEmpty();
+                if (down) {
+                    cond = n.preds.isEmpty();
+                }
+
+                if (cond) {
+
+                    if (prev != null && next != null) {
+                        n.crossingNumber = (prev.crossingNumber + next.crossingNumber) / 2;
+                    } else if (prev != null) {
+                        n.crossingNumber = prev.crossingNumber;
+                    } else if (next != null) {
+                        n.crossingNumber = next.crossingNumber;
+                    }
+                }
+            }
+        }
+
+        private void upSweep() {
+            // Upsweep
+            for (int i = layerCount - 2; i >= 0; i--) {
+
+                for (LayoutNode n : layers[i]) {
+                    n.crossingNumber = 0;
+                }
+
+                for (LayoutNode n : layers[i]) {
+
+                    int count = 0;
+                    int sum = 0;
+                    for (LayoutEdge e : n.succs) {
+                        int cur = e.to.x + e.relativeTo;
+                        int factor = 1;
+                        if (e.vip) {
+                            factor = VIP_BONUS;
+                        }
+                        sum += cur*factor;
+                        count+=factor;
+                    }
+
+                    if (count > 0) {
+                        sum /= count;
+                        n.crossingNumber = sum;
+                    }
+
+                }
+
+                updateCrossingNumbers(i, false);
+                Collections.sort(layers[i], crossingNodeComparator);
+                updateXOfLayer(i);
+
+                int z = 0;
+                for (LayoutNode n : layers[i]) {
+                    n.pos = z;
+                    z++;
+                }
+            }
+        }
+
+        @Override
+        public void postCheck() {
+
+            HashSet<LayoutNode> visited = new HashSet<>();
+            for (int i = 0; i < layers.length; i++) {
+                for (LayoutNode n : layers[i]) {
+                    assert !visited.contains(n);
+                    assert n.layer == i;
+                    visited.add(n);
+                }
+            }
+
+        }
+    }
+
+    private class AssignYCoordinates extends AlgorithmPart {
+
+        @Override
+        protected void run() {
+            int curY = 0;
+
+            for (int i = 0; i < layers.length; i++) {
+                int maxHeight = 0;
+                int baseLine = 0;
+                int bottomBaseLine = 0;
+                for (LayoutNode n : layers[i]) {
+                    maxHeight = Math.max(maxHeight, n.height - n.yOffset - n.bottomYOffset);
+                    baseLine = Math.max(baseLine, n.yOffset);
+                    bottomBaseLine = Math.max(bottomBaseLine, n.bottomYOffset);
+                }
+
+                int maxXOffset = 0;
+                for (LayoutNode n : layers[i]) {
+                    if (n.vertex == null) {
+                        // Dummy node
+                        n.y = curY;
+                        n.height = maxHeight + baseLine + bottomBaseLine;
+
+                    } else {
+                        n.y = curY + baseLine + (maxHeight - (n.height - n.yOffset - n.bottomYOffset)) / 2 - n.yOffset;
+                    }
+
+                    for (LayoutEdge e : n.succs) {
+                        int curXOffset = Math.abs(n.x - e.to.x);
+                        maxXOffset = Math.max(curXOffset, maxXOffset);
+                    }
+                }
+
+                curY += maxHeight + baseLine + bottomBaseLine;
+                curY += layerOffset + (int) Math.sqrt(maxXOffset);
+            }
+        }
+    }
+
+    private class CreateDummyNodes extends AlgorithmPart {
+
+        private int oldNodeCount;
+
+        @Override
+        protected void preCheck() {
+            for (LayoutNode n : nodes) {
+                for (LayoutEdge e : n.succs) {
+                    assert e.from != null;
+                    assert e.from == n;
+                    assert e.from.layer < e.to.layer;
+                }
+
+                for (LayoutEdge e : n.preds) {
+                    assert e.to != null;
+                    assert e.to == n;
+                }
+            }
+        }
+
+        @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<>();
+                ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes);
+                for (LayoutNode n : currentNodes) {
+                    portHash.clear();
+
+                    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) {
+                            if (maxLayerLength != -1 && e.to.layer - e.from.layer > maxLayerLength/* && e.to.preds.size() > 1 && e.from.succs.size() > 1*/) {
+                                assert maxLayerLength > 2;
+                                e.to.preds.remove(e);
+                                e.from.succs.remove(e);
+
+                                LayoutEdge topEdge = null;
+
+                                if (combine == Combine.SAME_OUTPUTS && topNodeHash.containsKey(e.relativeFrom)) {
+                                    LayoutNode topNode = topNodeHash.get(e.relativeFrom);
+                                    topEdge = new LayoutEdge();
+                                    topEdge.relativeFrom = e.relativeFrom;
+                                    topEdge.from = e.from;
+                                    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 {
+
+                                    LayoutNode topNode = new LayoutNode();
+                                    topNode.layer = e.from.layer + 1;
+                                    topNode.width = DUMMY_WIDTH;
+                                    topNode.height = DUMMY_HEIGHT;
+                                    nodes.add(topNode);
+                                    topEdge = new LayoutEdge();
+                                    topEdge.relativeFrom = e.relativeFrom;
+                                    topEdge.from = e.from;
+                                    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);
+                                    bottomNodeHash.put(e.relativeFrom, new HashMap<Integer, LayoutNode>());
+                                }
+
+                                HashMap<Integer, LayoutNode> hash = bottomNodeHash.get(e.relativeFrom);
+
+                                LayoutNode bottomNode = null;
+                                if (hash.containsKey(e.to.layer)) {
+                                    bottomNode = hash.get(e.to.layer);
+                                } else {
+
+                                    bottomNode = new LayoutNode();
+                                    bottomNode.layer = e.to.layer - 1;
+                                    bottomNode.width = DUMMY_WIDTH;
+                                    bottomNode.height = DUMMY_HEIGHT;
+                                    nodes.add(bottomNode);
+                                    hash.put(e.to.layer, bottomNode);
+                                }
+
+                                LayoutEdge bottomEdge = new LayoutEdge();
+                                bottomEdge.relativeTo = e.relativeTo;
+                                bottomEdge.to = e.to;
+                                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);
+
+                            } else {
+                                Integer i = e.relativeFrom;
+                                if (!portHash.containsKey(i)) {
+                                    portHash.put(i, new ArrayList<LayoutEdge>());
+                                }
+                                portHash.get(i).add(e);
+                            }
+                        }
+                    }
+
+                    succs = new ArrayList<>(n.succs);
+                    for (LayoutEdge e : succs) {
+
+                        Integer i = e.relativeFrom;
+                        if (portHash.containsKey(i)) {
+
+                            List<LayoutEdge> list = portHash.get(i);
+                            Collections.sort(list, comparator);
+
+                            if (list.size() == 1) {
+                                processSingleEdge(list.get(0));
+                            } else {
+
+                                int maxLayer = list.get(0).to.layer;
+                                for (LayoutEdge curEdge : list) {
+                                    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();
+                                nodes[0].width = dummyWidth;
+                                nodes[0].height = dummyHeight;
+                                nodes[0].layer = n.layer + 1;
+                                nodes[0].preds.add(edges[0]);
+                                edges[0].to = nodes[0];
+                                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]);
+                                    nodes[j] = new LayoutNode();
+                                    nodes[j].width = dummyWidth;
+                                    nodes[j].height = dummyHeight;
+                                    nodes[j].layer = n.layer + j + 1;
+                                    nodes[j].preds.add(edges[j]);
+                                    edges[j].to = nodes[j];
+                                    edges[j].relativeTo = nodes[j].width / 2;
+                                }
+
+                                for (LayoutEdge curEdge : list) {
+                                    assert curEdge.to.layer - n.layer - 2 >= 0;
+                                    assert curEdge.to.layer - n.layer - 2 < cnt;
+                                    LayoutNode anchor = nodes[curEdge.to.layer - n.layer - 2];
+                                    anchor.succs.add(curEdge);
+                                    curEdge.from = anchor;
+                                    curEdge.relativeFrom = anchor.width / 2;
+                                    n.succs.remove(curEdge);
+                                }
+
+                            }
+
+                            portHash.remove(i);
+                        }
+                    }
+                }
+            } else if (combine == Combine.SAME_INPUTS) {
+                throw new UnsupportedOperationException("Currently not supported");
+            } else {
+                ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes);
+                for (LayoutNode n : currentNodes) {
+                    for (LayoutEdge e : n.succs) {
+                        processSingleEdge(e);
+                    }
+                }
+            }
+        }
+
+        private void processSingleEdge(LayoutEdge e) {
+            LayoutNode n = e.from;
+            if (e.to.layer > n.layer + 1) {
+                LayoutEdge last = e;
+                for (int i = n.layer + 1; i < last.to.layer; i++) {
+                    last = addBetween(last, i);
+                }
+            }
+        }
+
+        private LayoutEdge addBetween(LayoutEdge e, int layer) {
+            LayoutNode n = new LayoutNode();
+            n.width = dummyWidth;
+            n.height = dummyHeight;
+            n.layer = layer;
+            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;
+            result.to = e.to;
+            result.relativeTo = e.relativeTo;
+            e.relativeTo = n.width / 2;
+            e.to.preds.remove(e);
+            e.to.preds.add(result);
+            e.to = n;
+            return result;
+        }
+
+        @Override
+        public void printStatistics() {
+            System.out.println("Dummy nodes created: " + (nodes.size() - oldNodeCount));
+        }
+
+        @Override
+        public void postCheck() {
+            ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes);
+            for (LayoutNode n : currentNodes) {
+                for (LayoutEdge e : n.succs) {
+                    assert e.from.layer == e.to.layer - 1;
+                }
+            }
+
+            for (int i = 0; i < layers.length; i++) {
+                assert layers[i].size() > 0;
+                for (LayoutNode n : layers[i]) {
+                    assert n.layer == i;
+                }
+            }
+        }
+    }
+
+    private class AssignLayers extends AlgorithmPart {
+
+        @Override
+        public void preCheck() {
+            for (LayoutNode n : nodes) {
+                assert n.layer == -1;
+            }
+        }
+
+        @Override
+        protected void run() {
+
+            List<LayoutNode> insertOrder = new ArrayList<>();
+
+            HashSet<LayoutNode> set = new HashSet<>();
+            for (LayoutNode n : nodes) {
+                if (n.preds.size() == 0) {
+                    set.add(n);
+                    insertOrder.add(n);
+                    n.layer = 0;
+                }
+            }
+
+            int z = minLayerDifference;
+            HashSet<LayoutNode> newSet = new HashSet<>();
+            HashSet<LayoutNode> failed = new HashSet<>();
+            while (!set.isEmpty()) {
+
+                newSet.clear();
+                failed.clear();
+
+                for (LayoutNode n : set) {
+
+                    for (LayoutEdge se : n.succs) {
+                        LayoutNode s = se.to;
+                        if (!newSet.contains(s) && !failed.contains(s)) {
+                            boolean ok = true;
+                            for (LayoutEdge pe : s.preds) {
+                                LayoutNode p = pe.from;
+                                if (p.layer == -1) {
+                                    ok = false;
+                                    break;
+                                }
+                            }
+
+                            if (ok) {
+                                newSet.add(s);
+                            } else {
+                                failed.add(s);
+                            }
+                        }
+                    }
+
+                }
+
+                for (LayoutNode n : newSet) {
+                    n.layer = z;
+                    insertOrder.add(n);
+                }
+
+                // Swap sets
+                HashSet<LayoutNode> tmp = set;
+                set = newSet;
+                newSet = tmp;
+                z += minLayerDifference;
+            }
+
+            optimize(insertOrder);
+
+            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;
+                n.layer = 0;
+                assert n.layer == 0;
+            }
+        }
+
+        public void optimize(List<LayoutNode> insertOrder) {
+            for (int i = insertOrder.size() - 1; i >= 0; i--) {
+                LayoutNode cur = insertOrder.get(i);
+                if (cur.succs.size() > cur.preds.size()) {
+                    int minLayer = cur.succs.get(0).to.layer;
+                    for (LayoutEdge e : cur.succs) {
+                        minLayer = Math.min(minLayer, e.to.layer);
+                    }
+                    cur.layer = minLayer - 1;
+                }
+            }
+        }
+
+        @Override
+        public void postCheck() {
+            for (LayoutNode n : nodes) {
+                assert n.layer >= 0;
+                assert n.layer < layerCount;
+                for (LayoutEdge e : n.succs) {
+                    assert e.from.layer < e.to.layer;
+                }
+            }
+        }
+    }
+
+    private class ReverseEdges extends AlgorithmPart {
+
+        private HashSet<LayoutNode> visited;
+        private HashSet<LayoutNode> active;
+
+        @Override
+        protected void run() {
+
+            // Remove self-edges
+            for (LayoutNode node : nodes) {
+                ArrayList<LayoutEdge> succs = new ArrayList<>(node.succs);
+                for (LayoutEdge e : succs) {
+                    assert e.from == node;
+                    if (e.to == node) {
+                        node.succs.remove(e);
+                        node.preds.remove(e);
+                    }
+                }
+            }
+
+            // Reverse inputs of roots
+            for (LayoutNode node : nodes) {
+                if (node.vertex.isRoot()) {
+                    boolean ok = true;
+                    for (LayoutEdge e : node.preds) {
+                        if (e.from.vertex.isRoot()) {
+                            ok = false;
+                            break;
+                        }
+                    }
+                    if (ok) {
+                        reverseAllInputs(node);
+                    }
+                }
+            }
+
+
+            // Start DFS and reverse back edges
+            visited = new HashSet<>();
+            active = new HashSet<>();
+            for (LayoutNode node : nodes) {
+                DFS(node);
+            }
+
+
+            for (LayoutNode node : nodes) {
+
+                SortedSet<Integer> reversedDown = new TreeSet<>();
+
+                for (LayoutEdge e : node.succs) {
+                    if (reversedLinks.contains(e.link)) {
+                        reversedDown.add(e.relativeFrom);
+                    }
+                }
+
+
+                SortedSet<Integer> reversedUp = null;
+                if (reversedDown.size() == 0) {
+                    reversedUp = new TreeSet<>(Collections.reverseOrder());
+                } else {
+                    reversedUp = new TreeSet<>();
+                }
+
+                for (LayoutEdge e : node.preds) {
+                    if (reversedLinks.contains(e.link)) {
+                        reversedUp.add(e.relativeTo);
+                    }
+                }
+
+                final int offset = X_OFFSET + DUMMY_WIDTH;
+
+                int curX = 0;
+                int curWidth = node.width + reversedDown.size() * offset;
+                for (int pos : reversedDown) {
+                    ArrayList<LayoutEdge> reversedSuccs = new ArrayList<>();
+                    for (LayoutEdge e : node.succs) {
+                        if (e.relativeFrom == pos && reversedLinks.contains(e.link)) {
+                            reversedSuccs.add(e);
+                            e.relativeFrom = curWidth;
+                        }
+                    }
+
+                    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));
+                    for (LayoutEdge e : reversedSuccs) {
+                        reversedLinkStartPoints.put(e.link, startPoints);
+                    }
+
+                    node.inOffsets.put(pos, -curX);
+                    curX += offset;
+                    node.height += offset;
+                    node.yOffset += offset;
+                    curWidth -= offset;
+                }
+                node.width += reversedDown.size() * offset;
+
+                if (reversedDown.size() == 0) {
+                    curX = offset;
+                } else {
+                    curX = -offset;
+                }
+
+                curX = 0;
+                int minX = 0;
+                if (reversedDown.size() != 0) {
+                    minX = -offset * reversedUp.size();
+                }
+
+                int oldNodeHeight = node.height;
+                for (int pos : reversedUp) {
+                    ArrayList<LayoutEdge> reversedPreds = new ArrayList<>();
+                    for (LayoutEdge e : node.preds) {
+                        if (e.relativeTo == pos && reversedLinks.contains(e.link)) {
+                            if (reversedDown.size() == 0) {
+                                e.relativeTo = node.width + offset;
+                            } else {
+                                e.relativeTo = curX - offset;
+                            }
+
+                            reversedPreds.add(e);
+                        }
+                    }
+                    node.height += offset;
+                    ArrayList<Point> endPoints = new ArrayList<>();
+
+                    if (reversedDown.size() == 0) {
+
+                        curX += offset;
+                        node.width += offset;
+                        endPoints.add(new Point(node.width, node.height));
+
+                    } else {
+                        curX -= offset;
+                        node.width += offset;
+                        endPoints.add(new Point(curX, node.height));
+                    }
+
+                    node.outOffsets.put(pos - minX, curX);
+                    curX += offset;
+                    node.bottomYOffset += offset;
+
+
+                    endPoints.add(new Point(pos, node.height));
+                    endPoints.add(new Point(pos, oldNodeHeight));
+                    for (LayoutEdge e : reversedPreds) {
+                        reversedLinkEndPoints.put(e.link, endPoints);
+                    }
+                }
+
+
+                if (minX < 0) {
+                    for (LayoutEdge e : node.preds) {
+                        e.relativeTo -= minX;
+                    }
+
+                    for (LayoutEdge e : node.succs) {
+                        e.relativeFrom -= minX;
+                    }
+
+                    node.xOffset = -minX;
+                    node.width += -minX;
+                }
+            }
+
+        }
+
+        private void DFS(LayoutNode startNode) {
+            if (visited.contains(startNode)) {
+                return;
+            }
+
+            Stack<LayoutNode> stack = new Stack<>();
+            stack.push(startNode);
+
+            while (!stack.empty()) {
+                LayoutNode node = stack.pop();
+
+                if (visited.contains(node)) {
+                    // Node no longer active
+                    active.remove(node);
+                    continue;
+                }
+
+                // Repush immediately to know when no longer active
+                stack.push(node);
+                visited.add(node);
+                active.add(node);
+
+                ArrayList<LayoutEdge> succs = new ArrayList<>(node.succs);
+                for (LayoutEdge e : succs) {
+                    if (active.contains(e.to)) {
+                        assert visited.contains(e.to);
+                        // Encountered back edge
+                        reverseEdge(e);
+                    } else if (!visited.contains(e.to) && (linksToFollow.size() == 0 || linksToFollow.contains(e.link))) {
+                        stack.push(e.to);
+                    }
+                }
+            }
+        }
+
+        private void reverseAllInputs(LayoutNode node) {
+            for (LayoutEdge e : node.preds) {
+                assert !reversedLinks.contains(e.link);
+                reversedLinks.add(e.link);
+                node.succs.add(e);
+                e.from.preds.add(e);
+                e.from.succs.remove(e);
+                int oldRelativeFrom = e.relativeFrom;
+                int oldRelativeTo = e.relativeTo;
+                e.to = e.from;
+                e.from = node;
+                e.relativeFrom = oldRelativeTo;
+                e.relativeTo = oldRelativeFrom;
+            }
+            node.preds.clear();
+        }
+
+        private void reverseEdge(LayoutEdge e) {
+            assert !reversedLinks.contains(e.link);
+            reversedLinks.add(e.link);
+
+            LayoutNode oldFrom = e.from;
+            LayoutNode oldTo = e.to;
+            int oldRelativeFrom = e.relativeFrom;
+            int oldRelativeTo = e.relativeTo;
+
+            e.from = oldTo;
+            e.to = oldFrom;
+            e.relativeFrom = oldRelativeTo;
+            e.relativeTo = oldRelativeFrom;
+
+            oldFrom.succs.remove(e);
+            oldFrom.preds.add(e);
+            oldTo.preds.remove(e);
+            oldTo.succs.add(e);
+        }
+
+        @Override
+        public void postCheck() {
+
+            for (LayoutNode n : nodes) {
+
+                HashSet<LayoutNode> curVisited = new HashSet<>();
+                Queue<LayoutNode> queue = new LinkedList<>();
+                for (LayoutEdge e : n.succs) {
+                    LayoutNode s = e.to;
+                    queue.add(s);
+                    curVisited.add(s);
+                }
+
+                while (!queue.isEmpty()) {
+                    LayoutNode curNode = queue.remove();
+
+                    for (LayoutEdge e : curNode.succs) {
+                        assert e.to != n;
+                        if (!curVisited.contains(e.to)) {
+                            queue.add(e.to);
+                            curVisited.add(e.to);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    private Comparator<Link> linkComparator = new Comparator<Link>() {
+
+        @Override
+        public int compare(Link l1, Link l2) {
+
+            int result = l1.getFrom().getVertex().compareTo(l2.getFrom().getVertex());
+            if (result != 0) {
+                return result;
+            }
+            result = l1.getTo().getVertex().compareTo(l2.getTo().getVertex());
+            if (result != 0) {
+                return result;
+            }
+            result = l1.getFrom().getRelativePosition().x - l2.getFrom().getRelativePosition().x;
+            if (result != 0) {
+                return result;
+            }
+            result = l1.getTo().getRelativePosition().x - l2.getTo().getRelativePosition().x;
+            return result;
+        }
+    };
+
+    private class BuildDatastructure extends AlgorithmPart {
+
+        @Override
+        protected void run() {
+            // Set up nodes
+            List<Vertex> vertices = new ArrayList<>(graph.getVertices());
+            Collections.sort(vertices);
+
+            for (Vertex v : vertices) {
+                LayoutNode node = new LayoutNode();
+                Dimension size = v.getSize();
+                node.width = (int) size.getWidth();
+                node.height = (int) size.getHeight();
+                node.vertex = v;
+                nodes.add(node);
+                vertexToLayoutNode.put(v, node);
+            }
+
+            // Set up edges
+            List<Link> links = new ArrayList<>(graph.getLinks());
+            Collections.sort(links, linkComparator);
+            for (Link l : links) {
+                LayoutEdge edge = new LayoutEdge();
+                assert vertexToLayoutNode.containsKey(l.getFrom().getVertex());
+                assert vertexToLayoutNode.containsKey(l.getTo().getVertex());
+                edge.from = vertexToLayoutNode.get(l.getFrom().getVertex());
+                edge.to = vertexToLayoutNode.get(l.getTo().getVertex());
+                edge.relativeFrom = l.getFrom().getRelativePosition().x;
+                edge.relativeTo = l.getTo().getRelativePosition().x;
+                edge.link = l;
+                edge.from.succs.add(edge);
+                edge.to.preds.add(edge);
+                edge.vip = l.isVIP();
+            //assert edge.from != edge.to; // No self-loops allowed
+            }
+
+            for (Link l : importantLinks) {
+                if (!vertexToLayoutNode.containsKey(l.getFrom().getVertex()) ||
+                        vertexToLayoutNode.containsKey(l.getTo().getVertex())) {
+                    continue;
+                }
+                LayoutNode from = vertexToLayoutNode.get(l.getFrom().getVertex());
+                LayoutNode to = vertexToLayoutNode.get(l.getTo().getVertex());
+                for (LayoutEdge e : from.succs) {
+                    if (e.to == to) {
+                        linksToFollow.add(e.link);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void postCheck() {
+
+            assert vertexToLayoutNode.keySet().size() == nodes.size();
+            assert nodes.size() == graph.getVertices().size();
+
+            for (Vertex v : graph.getVertices()) {
+
+                LayoutNode node = vertexToLayoutNode.get(v);
+                assert node != null;
+
+                for (LayoutEdge e : node.succs) {
+                    assert e.from == node;
+                }
+
+                for (LayoutEdge e : node.preds) {
+                    assert e.to == node;
+                }
+
+            }
+        }
+    }
+
+    @Override
+    public void doRouting(LayoutGraph graph) {
+        // Do nothing for now
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Node.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.hierarchicallayout;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Node<N, E> {
+
+    private N data;
+    private List<Edge<N, E>> inEdges;
+    private List<Edge<N, E>> outEdges;
+    private boolean visited;
+    private boolean active;
+    private boolean reachable;
+    private Graph<N, E> graph;
+
+    protected boolean isVisited() {
+        return visited;
+    }
+
+    protected void setVisited(boolean b) {
+        visited = b;
+    }
+
+    protected boolean isReachable() {
+        return reachable;
+    }
+
+    protected void setReachable(boolean b) {
+        reachable = b;
+    }
+
+    protected boolean isActive() {
+        return active;
+    }
+
+    protected void setActive(boolean b) {
+        active = b;
+    }
+
+    public int getInDegree() {
+        return getInDegree(true);
+    }
+
+    public int getInDegree(boolean countSelfLoops) {
+        if (countSelfLoops) {
+            return inEdges.size();
+        } else {
+            int cnt = 0;
+            for (Edge<N, E> e : inEdges) {
+                if (e.getSource() != this) {
+                    cnt++;
+                }
+            }
+            return cnt;
+        }
+    }
+
+    public int getOutDegree() {
+        return outEdges.size();
+    }
+
+    protected Node(Graph<N, E> graph, N data) {
+        setData(data);
+        this.graph = graph;
+        inEdges = new ArrayList<>();
+        outEdges = new ArrayList<>();
+    }
+
+    protected void addInEdge(Edge<N, E> e) {
+        inEdges.add(e);
+    }
+
+    public Graph<N, E> getGraph() {
+        return graph;
+    }
+
+    protected void addOutEdge(Edge<N, E> e) {
+        outEdges.add(e);
+    }
+
+    protected void removeInEdge(Edge<N, E> e) {
+        //assert inEdges.contains(e);
+        inEdges.remove(e);
+    }
+
+    protected void removeOutEdge(Edge<N, E> e) {
+        //assert outEdges.contains(e);
+        outEdges.remove(e);
+    }
+
+    public List<Edge<N, E>> getInEdges() {
+        return Collections.unmodifiableList(inEdges);
+    }
+
+    public List<Edge<N, E>> getOutEdges() {
+        return Collections.unmodifiableList(outEdges);
+    }
+
+    public List<Node<N, E>> getSuccessors() {
+        ArrayList<Node<N, E>> succ = new ArrayList<>();
+        for (Edge<N, E> e : getOutEdges()) {
+            Node<N, E> n = e.getDest();
+            if (!succ.contains(n)) {
+                succ.add(n);
+            }
+        }
+        return succ;
+    }
+
+    public List<Node<N, E>> getPredecessors() {
+        ArrayList<Node<N, E>> pred = new ArrayList<>();
+        for (Edge<N, E> e : getInEdges()) {
+            Node<N, E> n = e.getSource();
+            if (!pred.contains(n)) {
+                pred.add(n);
+            }
+        }
+        return pred;
+    }
+
+    public N getData() {
+        return data;
+    }
+
+    public void setData(N d) {
+        data = d;
+    }
+
+    @Override
+    public String toString() {
+        return "Node: " + data;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Timing.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Timing {
+
+    private long lastValue;
+    private long sum;
+    private String name;
+
+    public Timing(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        long val = sum;
+        if (lastValue != 0) {
+            // Timer running
+            long newValue = System.nanoTime();
+            val += (newValue - lastValue);
+        }
+        return "Timing for " + name + " is: " + val / 1000000 + " ms";
+    }
+
+    public void print() {
+        System.out.println(toString());
+    }
+
+    public void start() {
+        lastValue = System.nanoTime();
+    }
+
+    public void stop() {
+        if (lastValue == 0) {
+            throw new IllegalStateException("You must call start before stop");
+        }
+        long newValue = System.nanoTime();
+        sum += newValue - lastValue;
+        lastValue = 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.layout" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.layout.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.layout
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/layout/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.layout-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=cb0889d9
+build.xml.script.CRC32=d65fccb9
+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=cb0889d9
+nbproject/build-impl.xml.script.CRC32=7f82736d
+nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,14 @@
+<?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.layout</code-name-base>
+            <suite-component/>
+            <module-dependencies/>
+            <public-packages>
+                <package>com.sun.hotspot.igv.layout</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Layout
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.layout;
+
+import java.util.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class LayoutGraph {
+
+    private Set<? extends Link> links;
+    private SortedSet<Vertex> vertices;
+    private HashMap<Vertex, Set<Port>> inputPorts;
+    private HashMap<Vertex, Set<Port>> outputPorts;
+    private HashMap<Port, Set<Link>> portLinks;
+
+    public LayoutGraph(Set<? extends Link> links) {
+        this(links, new HashSet<Vertex>());
+    }
+
+    public LayoutGraph(Set<? extends Link> links, Set<? extends Vertex> additionalVertices) {
+        this.links = links;
+        assert verify();
+
+        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();
+            Port p2 = l.getTo();
+            Vertex v1 = p.getVertex();
+            Vertex v2 = p2.getVertex();
+
+            if (!vertices.contains(v1)) {
+
+                outputPorts.put(v1, new HashSet<Port>(1));
+                inputPorts.put(v1, new HashSet<Port>(3));
+                vertices.add(v1);
+                assert vertices.contains(v1);
+            }
+
+            if (!vertices.contains(v2)) {
+                vertices.add(v2);
+                assert vertices.contains(v2);
+                outputPorts.put(v2, new HashSet<Port>(1));
+                inputPorts.put(v2, new HashSet<Port>(3));
+            }
+
+            if (!portLinks.containsKey(p)) {
+                HashSet<Link> hashSet = new HashSet<>(3);
+                portLinks.put(p, hashSet);
+            }
+
+            if (!portLinks.containsKey(p2)) {
+                portLinks.put(p2, new HashSet<Link>(3));
+            }
+
+            outputPorts.get(v1).add(p);
+            inputPorts.get(v2).add(p2);
+
+            portLinks.get(p).add(l);
+            portLinks.get(p2).add(l);
+        }
+
+        for (Vertex v : additionalVertices) {
+            if (!vertices.contains(v)) {
+                outputPorts.put(v, new HashSet<Port>(1));
+                inputPorts.put(v, new HashSet<Port>(3));
+                vertices.add(v);
+                vertices.contains(v);
+            }
+        }
+    }
+
+    public Set<Port> getInputPorts(Vertex v) {
+        return this.inputPorts.get(v);
+    }
+
+    public Set<Port> getOutputPorts(Vertex v) {
+        return this.outputPorts.get(v);
+    }
+
+    public Set<Link> getPortLinks(Port p) {
+        return portLinks.get(p);
+    }
+
+    public Set<? extends Link> getLinks() {
+        return links;
+    }
+
+    public boolean verify() {
+        return true;
+    }
+
+    public SortedSet<Vertex> getVertices() {
+        return vertices;
+    }
+
+    private void markNotRoot(Set<Vertex> notRootSet, Vertex v, Vertex startingVertex) {
+
+        if (notRootSet.contains(v)) {
+            return;
+        }
+        if (v != startingVertex) {
+            notRootSet.add(v);
+        }
+        Set<Port> outPorts = getOutputPorts(v);
+        for (Port p : outPorts) {
+            Set<Link> portLinks = getPortLinks(p);
+            for (Link l : portLinks) {
+                Port other = l.getTo();
+                Vertex otherVertex = other.getVertex();
+                if (otherVertex != startingVertex) {
+                    markNotRoot(notRootSet, otherVertex, startingVertex);
+                }
+            }
+        }
+    }
+
+    // Returns a set of vertices with the following properties:
+    // - All Vertices in the set startingRoots are elements of the set.
+    // - When starting a DFS at every vertex in the set, every vertex of the 
+    //   whole graph is visited.
+    public Set<Vertex> findRootVertices(Set<Vertex> startingRoots) {
+
+        Set<Vertex> notRootSet = new HashSet<>();
+        for (Vertex v : startingRoots) {
+            if (!notRootSet.contains(v)) {
+                markNotRoot(notRootSet, v, v);
+            }
+        }
+
+        Set<Vertex> tmpVertices = getVertices();
+        for (Vertex v : tmpVertices) {
+            if (!notRootSet.contains(v)) {
+                if (this.getInputPorts(v).size() == 0) {
+                    markNotRoot(notRootSet, v, v);
+                }
+            }
+        }
+
+        for (Vertex v : tmpVertices) {
+            if (!notRootSet.contains(v)) {
+                markNotRoot(notRootSet, v, v);
+            }
+        }
+
+        Set<Vertex> result = new HashSet<>();
+        for (Vertex v : tmpVertices) {
+            if (!notRootSet.contains(v)) {
+                result.add(v);
+            }
+        }
+        assert tmpVertices.size() == 0 || result.size() > 0;
+        return result;
+    }
+
+    public Set<Vertex> findRootVertices() {
+        return findRootVertices(new HashSet<Vertex>());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutManager.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.layout;
+
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface LayoutManager {
+
+    public void doLayout(LayoutGraph graph);
+
+    public void doLayout(LayoutGraph graph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinks);
+
+    public void doRouting(LayoutGraph graph);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/Link.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.layout;
+
+import java.awt.Point;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface Link {
+
+    public Port getFrom();
+
+    public Port getTo();
+    
+    public boolean isVIP();
+
+    public List<Point> getControlPoints();
+
+    public void setControlPoints(List<Point> list);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/Port.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.layout;
+
+import java.awt.Point;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface Port {
+
+    public Vertex getVertex();
+
+    public Point getRelativePosition();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/Vertex.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.layout;
+
+import java.awt.Dimension;
+import java.awt.Point;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface Vertex extends Comparable<Vertex> {
+
+    public Dimension getSize();
+
+    public Point getPosition();
+
+    public void setPosition(Point p);
+
+    public boolean isRoot();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.coordinator" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.oracle.graal.visualizer.outline.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.oracle.graal.visualizer.outline
+OpenIDE-Module-Layer: com/oracle/graal/visualizer/outline/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/outline/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.coordinator-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=077de97c
+build.xml.script.CRC32=d29d586c
+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=077de97c
+nbproject/build-impl.xml.script.CRC32=03daa42d
+nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,144 @@
+<?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.oracle.graal.visualizer.outline</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>at.ssw.visualizer.cfg</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>
+                <package>com.oracle.graal.visualizer.outline</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,5 @@
+AdvancedOption_DisplayName_Coordinator=Settings
+AdvancedOption_Tooltip_Coordinator=Visualization Tool Settings
+CTL_OutlineTopComponent=Outline
+HINT_OutlineTopComponent=Displays loaded compilations.
+OpenIDE-Module-Name=OutlineView
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/CompilationNode.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.outline;
+
+import com.sun.hotspot.igv.data.*;
+import com.sun.hotspot.igv.data.services.GraphViewer;
+import java.awt.Image;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.Action;
+import javax.swing.JOptionPane;
+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.util.ImageUtilities;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.AbstractLookup;
+import org.openide.util.lookup.InstanceContent;
+import org.openide.util.lookup.Lookups;
+
+public class CompilationNode extends AbstractNode implements ChangedListener {
+
+    private CompilationNode(final Folder folder, Children children, InstanceContent content) {
+        super(children, new AbstractLookup(content));
+        this.setDisplayName(folder.getName());
+
+        if (folder instanceof Group) {
+            content.add(new OpenCookie() {
+
+                @Override
+                public void open() {
+                    final List<InputGraph> graphs = ((Group) folder).getGraphs();
+                    if (graphs.isEmpty()) {
+                        JOptionPane.showMessageDialog(null, "Cannot open compilation, because there was no snapshots recorded!");
+                    } else {
+                        Lookup.getDefault().lookup(GraphViewer.class).view(graphs.get(0));
+                    }
+                }
+            });
+        }
+        content.add(folder);
+        folder.getChangedEvent().addListener(this);
+    }
+
+    @Override
+    public void changed(Object folder) {
+        if (this.getChildren() == Children.LEAF) {
+            setChildren(createFolderChildren((Folder) folder));
+            this.fireIconChange();
+        }
+    }
+
+    private static class FolderChildren extends Children.Keys<Folder> {
+
+        private final Folder folder;
+
+        public FolderChildren(Folder folder) {
+            this.folder = folder;
+            folder.getChangedEvent().addListener(changedListener);
+        }
+
+        @Override
+        protected Node[] createNodes(Folder e) {
+            return new Node[]{new CompilationNode(e)};
+        }
+
+        @Override
+        public void addNotify() {
+            List<Folder> result = new ArrayList<>();
+            for (FolderElement o : folder.getElements()) {
+                if (o instanceof Folder) {
+                    result.add((Folder) o);
+                }
+            }
+            this.setKeys(result);
+        }
+        private final ChangedListener changedListener = new ChangedListener() {
+
+            @Override
+            public void changed(Object source) {
+                addNotify();
+            }
+        };
+    }
+
+    @Override
+    public Image getIcon(int i) {
+        if (this.getChildren() == Children.LEAF) {
+            return ImageUtilities.loadImage("com/oracle/graal/visualizer/outline/images/leaf_node.gif");
+        } else {
+            return ImageUtilities.loadImage("com/oracle/graal/visualizer/outline/images/node.gif");
+        }
+    }
+
+    protected CompilationNode(Folder folder) {
+        this(folder, createFolderChildren(folder), new InstanceContent());
+    }
+
+    private static Children createFolderChildren(Folder folder) {
+        for (FolderElement elem : folder.getElements()) {
+            if (elem instanceof Folder) {
+                return new FolderChildren(folder);
+            }
+        }
+        return Children.LEAF;
+    }
+
+    @Override
+    public Action[] getActions(boolean context) {
+        List<Action> actions = new ArrayList<>();
+        actions.add((Action) OpenAction.findObject(OpenAction.class, true));
+        actions.addAll(Lookups.forPath(OutlineTopComponent.NODE_ACTIONS_FOLDER).lookupAll(Action.class));
+        return actions.toArray(new Action[actions.size()]);
+    }
+
+    @Override
+    public Action getPreferredAction() {
+        return (Action) OpenAction.findObject(OpenAction.class, true);
+    }
+
+    @Override
+    public Image getOpenedIcon(int i) {
+        return getIcon(i);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/OutlineTopComponent.form	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-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"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
+  </AuxValues>
+
+  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
+  <SubComponents>
+    <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.support.JScrollPaneSupportLayout"/>
+    </Container>
+  </SubComponents>
+</Form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/OutlineTopComponent.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.outline;
+
+import com.oracle.graal.visualizer.outline.server.ServerPanel;
+import com.oracle.graal.visualizer.util.LookupUtils;
+import com.sun.hotspot.igv.data.GraphDocument;
+import java.awt.BorderLayout;
+import javax.swing.Action;
+import org.openide.actions.GarbageCollectAction;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.Toolbar;
+import org.openide.explorer.ExplorerManager;
+import org.openide.explorer.ExplorerUtils;
+import org.openide.explorer.view.BeanTreeView;
+import org.openide.util.NbBundle;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
+
+@TopComponent.Description(preferredID = OutlineTopComponent.PREFERRED_ID, persistenceType = TopComponent.PERSISTENCE_ALWAYS)
+@TopComponent.Registration(mode = "explorer", openAtStartup = true)
+@ActionID(category = "Window", id = "com.oracle.graal.visualizer.outline.OutlineTopComponent")
+@ActionReference(path = "Menu/Window")
+@TopComponent.OpenActionRegistration(displayName = "Outline", preferredID = OutlineTopComponent.PREFERRED_ID)
+public final class OutlineTopComponent extends TopComponent implements ExplorerManager.Provider {
+
+    public static final String GLOBAL_ACTIONS_FOLDER = "Actions/Outline/Global";
+    public static final String NODE_ACTIONS_FOLDER = "Actions/Outline/Nodes";
+    public static OutlineTopComponent instance;
+    public static final String PREFERRED_ID = "OutlineTopComponent";
+    private ExplorerManager manager;
+    private GraphDocument document;
+
+    private OutlineTopComponent() {
+        initComponents();
+
+        setName(NbBundle.getMessage(OutlineTopComponent.class, "CTL_OutlineTopComponent"));
+        setToolTipText(NbBundle.getMessage(OutlineTopComponent.class, "HINT_OutlineTopComponent"));
+
+        document = new GraphDocument();
+        initListView();
+        initToolbar();
+    }
+
+    private void initListView() {
+        manager = new ExplorerManager();
+        manager.setRootContext(new CompilationNode(document));
+        ((BeanTreeView) this.treeView).setRootVisible(false);
+        associateLookup(ExplorerUtils.createLookup(manager, getActionMap()));
+    }
+
+    private void initToolbar() {
+        Toolbar toolbar = new Toolbar();
+        this.add(toolbar, BorderLayout.NORTH);
+        for (Action a : LookupUtils.lookupActions(GLOBAL_ACTIONS_FOLDER, getLookup())) {
+            toolbar.add(a);
+        }
+        toolbar.add(GarbageCollectAction.get(GarbageCollectAction.class).getToolbarPresenter());
+        toolbar.add(new ServerPanel(getDocument()));
+    }
+
+    @Override
+    public ExplorerManager getExplorerManager() {
+        return manager;
+    }
+
+    public GraphDocument getDocument() {
+        return document;
+    }
+
+    public static OutlineTopComponent findInstance() {
+        return (OutlineTopComponent) WindowManager.getDefault().findTopComponent(PREFERRED_ID);
+    }
+
+    @Override
+    public int getPersistenceType() {
+        return TopComponent.PERSISTENCE_NEVER;
+    }
+
+    @Override
+    protected String preferredID() {
+        return PREFERRED_ID;
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        treeView = new BeanTreeView();
+
+        setLayout(new java.awt.BorderLayout());
+        add(treeView, java.awt.BorderLayout.CENTER);
+    }// </editor-fold>//GEN-END:initComponents
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JScrollPane treeView;
+    // End of variables declaration//GEN-END:variables
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/ImportAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.outline.actions;
+
+import com.oracle.graal.visualizer.outline.OutlineTopComponent;
+import com.sun.hotspot.igv.data.GraphDocument;
+import com.sun.hotspot.igv.data.serialization.Parser;
+import com.sun.hotspot.igv.data.serialization.XMLParser;
+import com.sun.hotspot.igv.settings.Settings;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import javax.swing.JFileChooser;
+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.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
+import org.openide.util.RequestProcessor;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+@ActionID(id = "com.oracle.graal.visualizer.outline.actions.ImportAction", category = "File")
+@ActionRegistration(displayName = "Import", iconBase="com/oracle/graal/visualizer/outline/images/import.png")
+@ActionReferences(value = {
+    @ActionReference(path = "Menu/File", position = 100),
+    @ActionReference(path = OutlineTopComponent.GLOBAL_ACTIONS_FOLDER)})
+public final class ImportAction implements ActionListener {
+
+    public static FileFilter getFileFilter() {
+        return new FileFilter() {
+
+            @Override
+            public boolean accept(File f) {
+                return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory();
+            }
+
+            @Override
+            public String getDescription() {
+                return "XML files (*.xml)";
+            }
+        };
+    }
+
+    @Override
+    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)));
+
+        if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
+            File file = fc.getSelectedFile();
+
+            File dir = file;
+            if (!dir.isDirectory()) {
+                dir = dir.getParentFile();
+            }
+
+            Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath());
+
+            try {
+                final FileInputStream inputStream = new FileInputStream(file);
+                final InputSource is = new InputSource(inputStream);
+
+                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() {
+
+                    @Override
+                    public void setProgress(double d) {
+                        try {
+                            int curAvailable = inputStream.available();
+                            int prog = (int) (basis * (double) (start - curAvailable) / (double) start);
+                            handle.progress(prog);
+                        } catch (IOException ex) {
+                        }
+                    }
+
+                    @Override
+                    public void setState(String state) {
+                        setProgress(0.0);
+                        handle.progress(state);
+                    }
+                };
+                final Parser parser = new Parser();
+                final OutlineTopComponent component = OutlineTopComponent.findInstance();
+
+                component.requestActive();
+
+                RequestProcessor.getDefault().post(new Runnable() {
+
+                    @Override
+                    public void run() {
+                        try {
+                            final GraphDocument document = parser.parse(is, parseMonitor);
+                            parseMonitor.setState("Finishing");
+                            SwingUtilities.invokeLater(new Runnable(){
+
+                                @Override
+                                public void run() {
+                                    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() + "\"";
+                            }
+                            NotifyDescriptor d = new NotifyDescriptor.Message(s, NotifyDescriptor.ERROR_MESSAGE);
+                            DialogDisplayer.getDefault().notify(d);
+                        }
+                        handle.finish();
+                    }
+                });
+
+            } catch (IOException ex) {
+                DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error reading file!", NotifyDescriptor.ERROR_MESSAGE));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/RemoveAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.outline.actions;
+
+import com.oracle.graal.visualizer.outline.OutlineTopComponent;
+import com.sun.hotspot.igv.data.FolderElement;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
+
+@ActionID(id = "com.oracle.graal.visualizer.outline.actions.RemoveAction", category = "Edit")
+@ActionRegistration(displayName = "Remove", iconBase = "com/oracle/graal/visualizer/outline/images/remove.png")
+@ActionReferences(value = {
+    @ActionReference(path = "Menu/File", position = 400),
+    @ActionReference(path = OutlineTopComponent.NODE_ACTIONS_FOLDER)})
+public final class RemoveAction implements ActionListener {
+
+    List<FolderElement> elements;
+
+    public RemoveAction(List<FolderElement> elements) {
+        this.elements = elements;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        for (FolderElement element : elements) {
+            element.getParent().removeElement(element);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/RemoveAllAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.outline.actions;
+
+import com.oracle.graal.visualizer.outline.OutlineTopComponent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
+
+@ActionID(id = "com.oracle.graal.visualizer.outline.actions.RemoveAllAction", category = "Edit")
+@ActionRegistration(displayName = "Remove all", iconBase = "com/oracle/graal/visualizer/outline/images/removeall.png")
+@ActionReferences(value = {
+    @ActionReference(path = "Menu/File", position = 500),
+    @ActionReference(path = OutlineTopComponent.GLOBAL_ACTIONS_FOLDER)})
+public final class RemoveAllAction implements ActionListener {
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        OutlineTopComponent.findInstance().getDocument().clear();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/SaveAllAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.outline.actions;
+
+import com.oracle.graal.visualizer.outline.OutlineTopComponent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
+
+@ActionID(id = "com.oracle.graal.visualizer.outline.actions.SaveAllAction", category = "File")
+@ActionRegistration(displayName = "Save all..", iconBase = "com/oracle/graal/visualizer/outline/images/saveall.gif")
+@ActionReferences(value = {
+    @ActionReference(path = "Menu/File", position = 300),
+    @ActionReference(path = OutlineTopComponent.GLOBAL_ACTIONS_FOLDER)})
+public final class SaveAllAction implements ActionListener {
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        final OutlineTopComponent component = OutlineTopComponent.findInstance();
+        SaveAsAction.save(component.getDocument());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/SaveAsAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.outline.actions;
+
+import com.oracle.graal.visualizer.outline.OutlineTopComponent;
+import com.sun.hotspot.igv.data.Folder;
+import com.sun.hotspot.igv.data.FolderElement;
+import com.sun.hotspot.igv.data.GraphDocument;
+import com.sun.hotspot.igv.data.serialization.Printer;
+import com.sun.hotspot.igv.settings.Settings;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.*;
+import java.util.List;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
+
+@ActionID(id = "com.oracle.graal.visualizer.outline.actions.SaveAsAction", category = "File")
+@ActionRegistration(displayName = "Save as...", iconBase="com/oracle/graal/visualizer/outline/images/save.png")
+@ActionReferences(value = {
+    @ActionReference(path = "Menu/File", position = 200),
+    @ActionReference(path = OutlineTopComponent.NODE_ACTIONS_FOLDER)})
+public final class SaveAsAction implements ActionListener {
+
+    private final List<FolderElement> elements;
+    
+    public SaveAsAction(List<FolderElement> elements) {
+        this.elements = elements;
+    }
+
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        GraphDocument doc = new GraphDocument();
+        outer: for (FolderElement element : elements) {
+            Folder cur = element.getParent();
+            while (cur instanceof FolderElement) {
+                FolderElement curElement = (FolderElement) cur;
+                if (elements.contains(curElement)) {
+                    continue outer;
+                }
+                cur = curElement.getParent();
+            }
+            
+            Folder previousParent = element.getParent();
+            doc.addElement(element);
+            element.setParent(previousParent);
+        }
+
+        save(doc);
+    }
+
+    public static void save(GraphDocument doc) {
+        JFileChooser fc = new JFileChooser();
+        fc.setFileFilter(ImportAction.getFileFilter());
+        fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT)));
+
+        if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
+            File file = fc.getSelectedFile();
+            if (!file.getName().contains(".")) {
+                file = new File(file.getAbsolutePath() + ".xml");
+            }
+
+            File dir = file;
+            if (!dir.isDirectory()) {
+                dir = dir.getParentFile();
+            }
+            Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath());
+            try {
+                try (Writer writer = new OutputStreamWriter(new FileOutputStream(file))) {
+                    Printer p = new Printer();
+                    p.export(writer, doc);
+                }
+            } catch (IOException e) {
+                JOptionPane.showMessageDialog(null, "Error writing file " + file.getAbsolutePath());
+            }
+        }
+    }
+}
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/import.png has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/leaf_node.gif has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/node.gif has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/remove.png has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/removeall.png has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/save.png has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/saveall.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/layer.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
+<filesystem>
+    <folder name="Actions"/>
+    
+    <folder name="Menu">
+        <folder name="File">
+            <file name="Separator2.instance_hidden"/>
+            <file name="Separator3.instance_hidden"/>
+            <file name="SeparatorOpen.instance_hidden"/>
+            <file name="SeparatorSave.instance">
+                <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                <attr name="position" intvalue="150"/>
+            </file>
+            <file name="SeparatorRemove.instance">
+                <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                <attr name="position" intvalue="350"/>
+            </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>
+        
+        <folder name="Edit">
+            <!-- Hidden menu entries from other modules -->
+            <file name="Separator1.instance_hidden"/>
+            <file name="Separator2.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">
+            
+            <!-- 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="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="Toolbars">
+        <file name="Build_hidden"/>
+        <file name="Clipboard_hidden"/>
+        <file name="Debug_hidden"/>
+        <file name="Debugging.xml_hidden"/>
+        <file name="File_hidden"/>
+        <file name="Memory_hidden"/>
+        <file name="Standard.xml_hidden"/>
+        <file name="UndoRedo_hidden"/>
+    </folder>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=NetworkConnection
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Client.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.outline.server;
+
+import com.sun.hotspot.igv.data.serialization.Parser;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class Client implements Runnable {
+
+    private Socket socket;
+    private ServerCallback callback;
+
+    public Client(Socket socket, ServerCallback callback) {
+        this.callback = callback;
+        this.socket = socket;
+    }
+
+    @Override
+    public void run() {
+        callback.connectionOpened(socket.getInetAddress());
+        try {
+            InputStream inputStream = new BufferedInputStream(socket.getInputStream());
+            InputSource is = new InputSource(inputStream);
+
+            try {
+                Parser parser = new Parser(callback);
+                parser.parse(is, null);
+            } catch (SAXException ex) {
+                throw new IOException(ex);
+            }
+        } catch (IOException ex) {
+        } finally {
+            try {
+                socket.close();
+            } catch (IOException ex) {
+            }
+            callback.connectionClosed();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Server.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.outline.server;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.util.RequestProcessor;
+
+public class Server {
+
+    private Runnable serverRunnable;
+    private ServerSocket serverSocket;
+    
+    private Server() {}
+    
+
+    public static Server start(final ServerCallback callback, int port) {
+
+        final Server server = new Server();
+        
+        try {
+            server.serverSocket = new java.net.ServerSocket(port);
+        } catch (IOException ex) {
+            NotifyDescriptor message = new NotifyDescriptor.Message("Could not create server. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
+            DialogDisplayer.getDefault().notifyLater(message);
+            return null;
+        }
+
+        Runnable runnable = new Runnable() {
+
+            @Override
+            public void run() {
+                while (true) {
+                    try {
+                        Socket clientSocket = server.serverSocket.accept();
+                        if (server.serverRunnable != this) {
+                            clientSocket.close();
+                            return;
+                        }
+                        RequestProcessor.getDefault().post(new Client(clientSocket, callback), 0, Thread.MAX_PRIORITY);
+                    } catch (IOException ex) {
+                        server.serverSocket = null;
+                        NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
+                        DialogDisplayer.getDefault().notifyLater(message);
+                        return;
+                    }
+                }
+            }
+        };
+
+        server.serverRunnable = runnable;
+        RequestProcessor.getDefault().post(runnable, 0, Thread.MAX_PRIORITY);
+        return server;
+    }
+
+    void shutdown() {
+        try {
+            serverSocket.close();
+        } catch (IOException ex) {
+        }
+        
+        serverSocket = null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/ServerCallback.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.outline.server;
+
+import com.sun.hotspot.igv.data.services.GroupCallback;
+import java.net.InetAddress;
+
+public interface ServerCallback extends GroupCallback {
+    
+    public void connectionOpened(InetAddress inetAddress);
+
+    public void connectionClosed();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/ServerPanel.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.outline.server;
+
+import com.sun.hotspot.igv.data.GraphDocument;
+import com.sun.hotspot.igv.data.Group;
+import com.sun.hotspot.igv.settings.Settings;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Font;
+import java.net.InetAddress;
+import java.util.prefs.PreferenceChangeEvent;
+import java.util.prefs.PreferenceChangeListener;
+import javax.swing.BorderFactory;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+public class ServerPanel extends JPanel {
+
+    private final static int BORDER_SIZE = 2;
+    JLabel label;
+    private Server server;
+    private int port = -1;
+    private int numberOfConnections;
+    private final GraphDocument document;
+    private final PreferenceChangeListener preferenceChanged = new PreferenceChangeListener() {
+
+        @Override
+        public void preferenceChange(PreferenceChangeEvent evt) {
+            updateServer();
+        }
+    };
+    private ServerCallback callback = new ServerCallback() {
+
+        @Override
+        public void connectionOpened(InetAddress inetAddress) {
+            SwingUtilities.invokeLater(new Runnable() {
+
+                @Override
+                public void run() {
+                    numberOfConnections++;
+                    updateLabel();
+                }
+            });
+        }
+
+        @Override
+        public void connectionClosed() {
+            SwingUtilities.invokeLater(new Runnable() {
+
+                @Override
+                public void run() {
+                    numberOfConnections--;
+                    updateLabel();
+                }
+            });
+        }
+
+        @Override
+        public void started(Group g) {
+            document.addElement(g);
+        }
+    };
+
+    private void updateLabel() {
+        if (numberOfConnections == 0) {
+            label.setText(String.format("Listening on %d", port));
+            label.setFont(label.getFont().deriveFont(Font.PLAIN));
+        } else {
+            label.setText(String.format("%d connections", numberOfConnections));
+            label.setFont(label.getFont().deriveFont(Font.BOLD));
+        }
+    }
+
+    private void updateServer() {
+        int curPort = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT));
+        if (curPort != port) {
+            port = curPort;
+            if (server != null) {
+                server.shutdown();
+            }
+            server = Server.start(callback, port);
+            SwingUtilities.invokeLater(new Runnable() {
+
+                @Override
+                public void run() {
+                    updateLabel();
+                }
+            });
+        }
+    }
+
+    public ServerPanel(GraphDocument document) {
+
+        this.document = document;
+        Settings.get().addPreferenceChangeListener(preferenceChanged);
+        label = new JLabel();
+        label.setBorder(BorderFactory.createEmptyBorder(0, BORDER_SIZE, 0, BORDER_SIZE));
+        this.setLayout(new BorderLayout());
+        this.add(label, BorderLayout.WEST);
+        updateServer();
+    }
+
+    public Component getToolbarPresenter() {
+        return label;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=SelectionCoordinator
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/SelectionCoordinator.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.settings" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.settings.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.settings
+OpenIDE-Module-Layer: com/sun/hotspot/igv/settings/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/settings/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.settings-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=8869440a
+build.xml.script.CRC32=7ef09117
+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=8869440a
+nbproject/build-impl.xml.script.CRC32=1a0e7f21
+nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,57 @@
+<?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.settings</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.jdesktop.layout</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.16.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.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.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>
+            </module-dependencies>
+            <public-packages>
+                <package>com.sun.hotspot.igv.settings</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,5 @@
+AdvancedOption_DisplayName_Settings=Settings
+AdvancedOption_Tooltip_Settings=Application Settings
+OpenIDE-Module-Name=Settings
+OptionsCategory_Name_View=General
+OptionsCategory_Title_View=View Settings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,47 @@
+/*
+ * 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.settings;
+
+import java.util.prefs.Preferences;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Settings {
+
+    public final static String NODE_TEXT = "nodeText";
+    public final static String NODE_TEXT_DEFAULT = "[idx] [name]";
+    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_DEFAULT = "4444";
+    public final static String DIRECTORY = "directory";
+    public final static String DIRECTORY_DEFAULT = System.getProperty("user.dir");
+
+    public static Preferences get() {
+        return Preferences.userNodeForPackage(Settings.class);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsCategory.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,58 @@
+/*
+ * 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.settings;
+
+import javax.swing.Icon;
+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;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class ViewOptionsCategory extends OptionsCategory {
+
+    @Override
+    public Icon getIcon() {
+        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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsPanelController.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,104 @@
+/*
+ * 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.settings;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import javax.swing.JComponent;
+import org.netbeans.spi.options.OptionsPanelController;
+import org.openide.util.HelpCtx;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+final class ViewOptionsPanelController extends OptionsPanelController {
+
+    private ViewPanel panel;
+    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);
+    }
+
+    private ViewPanel getPanel() {
+        if (panel == null) {
+            panel = new ViewPanel(this);
+        }
+        return panel;
+    }
+
+    void changed() {
+        if (!changed) {
+            changed = true;
+            pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true);
+        }
+        pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.form	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jPanel1" max="32767" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jPanel1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace pref="206" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JPanel" name="jPanel1">
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="1" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
+                      <Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
+                      <Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace min="-2" pref="39" max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="portSpinner" alignment="0" min="-2" pref="63" max="-2" attributes="0"/>
+                      <Component id="nodeWidthSpinner" alignment="0" min="-2" pref="63" max="-2" attributes="0"/>
+                      <Component id="jScrollPane1" alignment="0" min="-2" pref="365" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Group type="102" alignment="0" attributes="0">
+                          <Component id="jScrollPane1" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace type="separate" max="-2" attributes="0"/>
+                          <Group type="103" groupAlignment="3" attributes="0">
+                              <Component id="nodeWidthSpinner" alignment="3" min="-2" max="-2" attributes="0"/>
+                              <Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
+                          </Group>
+                          <EmptySpace type="separate" max="-2" attributes="0"/>
+                          <Group type="103" groupAlignment="3" attributes="0">
+                              <Component id="portSpinner" alignment="3" min="-2" max="-2" attributes="0"/>
+                              <Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
+                          </Group>
+                      </Group>
+                      <Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace min="-2" pref="73" max="-2" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="jLabel1">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Node Text"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel2">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Node Width"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JSpinner" name="portSpinner">
+        </Component>
+        <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+          <AuxValues>
+            <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+          </AuxValues>
+
+          <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+          <SubComponents>
+            <Component class="javax.swing.JTextArea" name="nodeTextArea">
+              <Properties>
+                <Property name="columns" type="int" value="20"/>
+                <Property name="rows" type="int" value="5"/>
+              </Properties>
+            </Component>
+          </SubComponents>
+        </Container>
+        <Component class="javax.swing.JSpinner" name="nodeWidthSpinner">
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel3">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Network Port"/>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,144 @@
+/*
+ * 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.settings;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+final class ViewPanel extends javax.swing.JPanel {
+
+    private final ViewOptionsPanelController controller;
+
+    ViewPanel(ViewOptionsPanelController controller) {
+        this.controller = controller;
+        initComponents();
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jPanel1 = new javax.swing.JPanel();
+        jLabel1 = new javax.swing.JLabel();
+        jLabel2 = new javax.swing.JLabel();
+        portSpinner = new javax.swing.JSpinner();
+        jScrollPane1 = new javax.swing.JScrollPane();
+        nodeTextArea = new javax.swing.JTextArea();
+        nodeWidthSpinner = new javax.swing.JSpinner();
+        jLabel3 = new javax.swing.JLabel();
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, "Node Text");
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, "Node Width");
+
+        nodeTextArea.setColumns(20);
+        nodeTextArea.setRows(5);
+        jScrollPane1.setViewportView(nodeTextArea);
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, "Network Port");
+
+        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
+        jPanel1.setLayout(jPanel1Layout);
+        jPanel1Layout.setHorizontalGroup(
+            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1Layout.createSequentialGroup()
+                .addContainerGap()
+                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(jLabel1)
+                    .add(jLabel3)
+                    .add(jLabel2))
+                .add(39, 39, 39)
+                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(portSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                    .add(nodeWidthSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                    .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 365, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
+                .addContainerGap())
+        );
+        jPanel1Layout.setVerticalGroup(
+            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(jPanel1Layout.createSequentialGroup()
+                .addContainerGap()
+                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+                    .add(jPanel1Layout.createSequentialGroup()
+                        .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                        .add(18, 18, 18)
+                        .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                            .add(nodeWidthSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                            .add(jLabel2))
+                        .add(18, 18, 18)
+                        .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+                            .add(portSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                            .add(jLabel3)))
+                    .add(jLabel1))
+                .add(73, 73, 73))
+        );
+
+        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(layout.createSequentialGroup()
+                .addContainerGap()
+                .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(layout.createSequentialGroup()
+                .addContainerGap()
+                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 232, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap(206, Short.MAX_VALUE))
+        );
+    }// </editor-fold>//GEN-END:initComponents
+    void load() {
+        nodeTextArea.setText(Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT));
+        nodeWidthSpinner.setValue(Integer.parseInt(Settings.get().get(Settings.NODE_WIDTH, Settings.NODE_WIDTH_DEFAULT)));
+        portSpinner.setValue(Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT)));
+    }
+
+    void store() {
+        Settings.get().put(Settings.NODE_TEXT, nodeTextArea.getText());
+        Settings.get().put(Settings.NODE_WIDTH, nodeWidthSpinner.getValue().toString());
+        Settings.get().put(Settings.PORT, portSpinner.getValue().toString());
+    }
+
+    boolean valid() {
+        return true;
+    }
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JLabel jLabel2;
+    private javax.swing.JLabel jLabel3;
+    private javax.swing.JPanel jPanel1;
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JTextArea nodeTextArea;
+    private javax.swing.JSpinner nodeWidthSpinner;
+    private javax.swing.JSpinner portSpinner;
+    // End of variables declaration//GEN-END:variables
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/layer.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,11 @@
+<?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="OptionsDialog">
+      <!-- <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 visualizer/Settings/src/com/sun/hotspot/igv/settings/settings.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.oracle.graal.visualizer.sharedactions" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.oracle.graal.visualizer.sharedactions.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.oracle.graal.visualizer.sharedactions
+OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/sharedactions/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.oracle.graal.visualizer.sharedactions-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/visualizer/SharedActions/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=c3bdef4e
+build.xml.script.CRC32=da3659b1
+build.xml.stylesheet.CRC32=a56c6a5b@2.47.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=c3bdef4e
+nbproject/build-impl.xml.script.CRC32=567ad23a
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,55 @@
+<?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.oracle.graal.visualizer.sharedactions</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.svg</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.actions</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.24.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>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.23.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.19.1</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages>
+                <package>com.oracle.graal.visualizer.sharedactions</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=SharedActions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ExportSVGAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.sharedactions;
+
+import com.sun.hotspot.igv.svg.BatikSVG;
+import java.awt.Graphics2D;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.*;
+import javax.swing.JFileChooser;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+import org.openide.util.NbPreferences;
+
+@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ExportSVGAction", category = "File")
+@ActionRegistration(displayName = "Export", iconBase = "com/oracle/graal/visualizer/sharedactions/images/export.png")
+@ActionReference(path = "Menu/File", position = 600)
+public class ExportSVGAction implements ActionListener {
+
+    private static final String PREFERENCE_DIR = "dir";
+    private ExportSVGCookie exportCookie;
+
+    public ExportSVGAction(ExportSVGCookie exportCookie) {
+        this.exportCookie = exportCookie;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent actionEvent) {
+        Graphics2D svgGenerator = BatikSVG.createGraphicsObject();
+        if (svgGenerator == null) {
+            NotifyDescriptor message = new NotifyDescriptor.Message("For export to SVG files the Batik SVG Toolkit must be intalled.", NotifyDescriptor.ERROR_MESSAGE);
+            DialogDisplayer.getDefault().notifyLater(message);
+            return;
+        }
+        
+        File f = selectFile();
+        if (f != null) {
+            exportCookie.paint(svgGenerator);
+            FileOutputStream os = null;
+            try {
+                os = new FileOutputStream(f);
+                Writer out = new OutputStreamWriter(os, "UTF-8");
+                BatikSVG.printToStream(svgGenerator, out, true);
+            } catch (FileNotFoundException e) {
+                NotifyDescriptor message = new NotifyDescriptor.Message("For export to SVG files the Batik SVG Toolkit must be intalled.", NotifyDescriptor.ERROR_MESSAGE);
+                DialogDisplayer.getDefault().notifyLater(message);
+
+            } catch (UnsupportedEncodingException e) {
+            } finally {
+                if (os != null) {
+                    try {
+                        os.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+        }
+    }
+
+    private File selectFile() {
+        JFileChooser fc = new JFileChooser();
+        fc.setFileFilter(new javax.swing.filechooser.FileFilter() {
+
+            @Override
+            public boolean accept(File f) {
+                return true;
+            }
+
+            @Override
+            public String getDescription() {
+                return "SVG files (*.svg)";
+            }
+        });
+        fc.setCurrentDirectory(new File(NbPreferences.forModule(ExportSVGAction.class).get(PREFERENCE_DIR, "~")));
+
+
+        if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
+            File file = fc.getSelectedFile();
+            if (!file.getName().contains(".")) {
+                file = new File(file.getAbsolutePath() + ".svg");
+            }
+
+            File dir = file;
+            if (!dir.isDirectory()) {
+                dir = dir.getParentFile();
+            }
+
+            NbPreferences.forModule(ExportSVGAction.class).put(PREFERENCE_DIR, dir.getAbsolutePath());
+            return file;
+        }
+
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ExportSVGCookie.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.sharedactions;
+
+import java.awt.Graphics2D;
+
+public interface ExportSVGCookie {
+    void paint(Graphics2D g);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ShowAllAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.sharedactions;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+
+@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ShowAllAction", category = "View")
+@ActionRegistration(displayName = "Fit Scene to Window", iconBase="com/oracle/graal/visualizer/sharedactions/images/autosize.gif")
+@ActionReference(path = "Menu/View", position = 500)
+public class ShowAllAction implements ActionListener {
+       
+    private List<ZoomCookie> zoomCookies;
+    
+    public ShowAllAction(List<ZoomCookie> zoomCookies) {
+        this.zoomCookies = zoomCookies;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        for (ZoomCookie c : zoomCookies) {
+            c.showAll();
+        }
+    }
+}   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomCookie.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.sharedactions;
+
+public interface ZoomCookie {
+    void zoomIn();
+    void zoomOut();
+    void showAll();
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomInAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.sharedactions;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+
+@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ZoomInAction", category = "View")
+@ActionRegistration(displayName = "Zoom In", iconBase="com/oracle/graal/visualizer/sharedactions/images/zoomin.gif")
+@ActionReference(path = "Menu/View", position = 600)
+public class ZoomInAction implements ActionListener {
+    
+    private List<ZoomCookie> zoomCookies;
+    
+    public ZoomInAction(List<ZoomCookie> zoomCookies) {
+        this.zoomCookies = zoomCookies;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        for (ZoomCookie c : zoomCookies) {
+            c.zoomIn();
+        }
+    }
+}   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomOutAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.sharedactions;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+
+@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ZoomOutAction", category = "View")
+@ActionRegistration(displayName = "Zoom Out", iconBase="com/oracle/graal/visualizer/sharedactions/images/zoomout.gif")
+@ActionReference(path = "Menu/View", position = 700)
+public class ZoomOutAction implements ActionListener {
+   
+    private List<ZoomCookie> zoomCookies;
+    
+    public ZoomOutAction(List<ZoomCookie> zoomCookies) {
+        this.zoomCookies = zoomCookies;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        for (ZoomCookie c : zoomCookies) {
+            c.zoomOut();
+        }
+    } 
+}   
Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/autosize.gif has changed
Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/export.png has changed
Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/zoomin.gif has changed
Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/zoomout.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.oracle.graal.visualizer.snapshots" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.oracle.graal.visualizer.snapshots.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,7 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.oracle.graal.visualizer.snapshots
+OpenIDE-Module-Layer: com/oracle/graal/visualizer/snapshots/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/snapshots/Bundle.properties
+OpenIDE-Module-Requires: org.openide.windows.WindowManager
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.oracle.graal.visualizer.snapshots-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/visualizer/SnapshotsView/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=8a85c130
+build.xml.script.CRC32=d28dc95d
+build.xml.stylesheet.CRC32=a56c6a5b@2.47.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=8a85c130
+nbproject/build-impl.xml.script.CRC32=dfcb8f66
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,204 @@
+cluster.path=\
+    ${nbplatform.active.dir}/ide:\
+    ${nbplatform.active.dir}/platform
+disabled.modules=\
+    com.jcraft.jsch,\
+    com.jcraft.jzlib,\
+    org.apache.commons.codec,\
+    org.apache.commons.httpclient,\
+    org.apache.commons.io,\
+    org.apache.commons.lang,\
+    org.apache.commons.logging,\
+    org.apache.ws.commons.util,\
+    org.apache.xml.resolver,\
+    org.apache.xmlrpc,\
+    org.eclipse.core.contenttype,\
+    org.eclipse.core.jobs,\
+    org.eclipse.core.net,\
+    org.eclipse.core.runtime,\
+    org.eclipse.core.runtime.compatibility.auth,\
+    org.eclipse.equinox.app,\
+    org.eclipse.equinox.common,\
+    org.eclipse.equinox.preferences,\
+    org.eclipse.equinox.registry,\
+    org.eclipse.equinox.security,\
+    org.eclipse.jgit,\
+    org.eclipse.mylyn.bugzilla.core,\
+    org.eclipse.mylyn.commons.core,\
+    org.eclipse.mylyn.commons.net,\
+    org.eclipse.mylyn.commons.xmlrpc,\
+    org.eclipse.mylyn.tasks.core,\
+    org.mozilla.rhino.patched,\
+    org.netbeans.api.debugger,\
+    org.netbeans.api.java.classpath,\
+    org.netbeans.api.xml,\
+    org.netbeans.core.browser,\
+    org.netbeans.core.execution,\
+    org.netbeans.core.ide,\
+    org.netbeans.core.io.ui,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.nativeaccess,\
+    org.netbeans.core.osgi,\
+    org.netbeans.lib.cvsclient,\
+    org.netbeans.lib.terminalemulator,\
+    org.netbeans.libs.antlr3.runtime,\
+    org.netbeans.libs.bytelist,\
+    org.netbeans.libs.commons_net,\
+    org.netbeans.libs.freemarker,\
+    org.netbeans.libs.git,\
+    org.netbeans.libs.ini4j,\
+    org.netbeans.libs.jaxb,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.junit4,\
+    org.netbeans.libs.jvyamlb,\
+    org.netbeans.libs.lucene,\
+    org.netbeans.libs.smack,\
+    org.netbeans.libs.svnClientAdapter,\
+    org.netbeans.libs.svnClientAdapter.javahl,\
+    org.netbeans.libs.svnClientAdapter.svnkit,\
+    org.netbeans.libs.swingx,\
+    org.netbeans.libs.xerces,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.bugtracking,\
+    org.netbeans.modules.bugtracking.bridge,\
+    org.netbeans.modules.bugzilla,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.csl.api,\
+    org.netbeans.modules.css.editor,\
+    org.netbeans.modules.css.lib,\
+    org.netbeans.modules.css.visual,\
+    org.netbeans.modules.db,\
+    org.netbeans.modules.db.core,\
+    org.netbeans.modules.db.dataview,\
+    org.netbeans.modules.db.drivers,\
+    org.netbeans.modules.db.kit,\
+    org.netbeans.modules.db.metadata.model,\
+    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.derby,\
+    org.netbeans.modules.dlight.nativeexecution,\
+    org.netbeans.modules.dlight.terminal,\
+    org.netbeans.modules.editor.bookmarks,\
+    org.netbeans.modules.editor.bracesmatching,\
+    org.netbeans.modules.editor.codetemplates,\
+    org.netbeans.modules.editor.completion,\
+    org.netbeans.modules.editor.guards,\
+    org.netbeans.modules.editor.indent.project,\
+    org.netbeans.modules.editor.kit,\
+    org.netbeans.modules.editor.macros,\
+    org.netbeans.modules.editor.structure,\
+    org.netbeans.modules.extbrowser,\
+    org.netbeans.modules.extexecution,\
+    org.netbeans.modules.extexecution.destroy,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.git,\
+    org.netbeans.modules.glassfish.common,\
+    org.netbeans.modules.gototest,\
+    org.netbeans.modules.gsf.codecoverage,\
+    org.netbeans.modules.gsf.testrunner,\
+    org.netbeans.modules.html,\
+    org.netbeans.modules.html.editor,\
+    org.netbeans.modules.html.editor.lib,\
+    org.netbeans.modules.html.lexer,\
+    org.netbeans.modules.html.parser,\
+    org.netbeans.modules.html.validation,\
+    org.netbeans.modules.httpserver,\
+    org.netbeans.modules.hudson,\
+    org.netbeans.modules.hudson.git,\
+    org.netbeans.modules.hudson.mercurial,\
+    org.netbeans.modules.hudson.subversion,\
+    org.netbeans.modules.hudson.tasklist,\
+    org.netbeans.modules.ide.kit,\
+    org.netbeans.modules.image,\
+    org.netbeans.modules.javascript.editing,\
+    org.netbeans.modules.javascript.hints,\
+    org.netbeans.modules.javascript.kit,\
+    org.netbeans.modules.javascript.refactoring,\
+    org.netbeans.modules.jellytools.ide,\
+    org.netbeans.modules.jumpto,\
+    org.netbeans.modules.keyring.impl,\
+    org.netbeans.modules.languages,\
+    org.netbeans.modules.languages.diff,\
+    org.netbeans.modules.languages.manifest,\
+    org.netbeans.modules.languages.yaml,\
+    org.netbeans.modules.lexer.nbbridge,\
+    org.netbeans.modules.localhistory,\
+    org.netbeans.modules.mercurial,\
+    org.netbeans.modules.netbinox,\
+    org.netbeans.modules.parsing.api,\
+    org.netbeans.modules.parsing.lucene,\
+    org.netbeans.modules.print.editor,\
+    org.netbeans.modules.project.ant,\
+    org.netbeans.modules.project.libraries,\
+    org.netbeans.modules.projectui,\
+    org.netbeans.modules.projectui.buildmenu,\
+    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.server,\
+    org.netbeans.modules.servletapi,\
+    org.netbeans.modules.spellchecker,\
+    org.netbeans.modules.spellchecker.apimodule,\
+    org.netbeans.modules.spellchecker.bindings.htmlxml,\
+    org.netbeans.modules.spellchecker.bindings.properties,\
+    org.netbeans.modules.spellchecker.dictionary_en,\
+    org.netbeans.modules.spellchecker.kit,\
+    org.netbeans.modules.spi.actions,\
+    org.netbeans.modules.subversion,\
+    org.netbeans.modules.swing.validation,\
+    org.netbeans.modules.target.iterator,\
+    org.netbeans.modules.tasklist.kit,\
+    org.netbeans.modules.tasklist.projectint,\
+    org.netbeans.modules.tasklist.todo,\
+    org.netbeans.modules.tasklist.ui,\
+    org.netbeans.modules.terminal,\
+    org.netbeans.modules.usersguide,\
+    org.netbeans.modules.utilities,\
+    org.netbeans.modules.utilities.project,\
+    org.netbeans.modules.versioning,\
+    org.netbeans.modules.versioning.indexingbridge,\
+    org.netbeans.modules.versioning.system.cvss.installer,\
+    org.netbeans.modules.versioning.util,\
+    org.netbeans.modules.web.client.tools.api,\
+    org.netbeans.modules.web.common,\
+    org.netbeans.modules.web.indent,\
+    org.netbeans.modules.xml,\
+    org.netbeans.modules.xml.axi,\
+    org.netbeans.modules.xml.catalog,\
+    org.netbeans.modules.xml.core,\
+    org.netbeans.modules.xml.jaxb.api,\
+    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.execution,\
+    org.openide.options,\
+    org.openide.util.enumerations
+## 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,\
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.6
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,78 @@
+<?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.oracle.graal.visualizer.snapshots</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.oracle.graal.visualizer.editor</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.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.modules.settings</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.33.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>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.19.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.11.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.48.1</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=SnapshotsView
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/SnapshotTopComponent.form	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <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="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <EmptySpace min="0" pref="400" max="32767" attributes="0"/>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <EmptySpace min="0" pref="300" max="32767" attributes="0"/>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+</Form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/SnapshotTopComponent.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.snapshots;
+
+import com.oracle.graal.visualizer.editor.EditorTopComponent;
+import com.oracle.graal.visualizer.util.LookupUtils;
+import com.sun.hotspot.igv.data.ChangedEvent;
+import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.util.RangeSlider;
+import com.sun.hotspot.igv.util.RangeSliderModel;
+import java.awt.BorderLayout;
+import javax.swing.JScrollPane;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.util.Lookup.Result;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
+
+@TopComponent.Description(preferredID = SnapshotTopComponent.PREFERRED_ID, persistenceType = TopComponent.PERSISTENCE_ALWAYS)
+@TopComponent.Registration(mode = "belowExplorer", openAtStartup = true)
+@ActionID(category = "Window", id = "com.oracle.graal.visualizer.snapshots.SnapshotTopComponent")
+@ActionReference(path = "Menu/Window")
+@TopComponent.OpenActionRegistration(displayName = "Snapshot", preferredID = SnapshotTopComponent.PREFERRED_ID)
+public final class SnapshotTopComponent extends TopComponent {
+    public static final String PREFERRED_ID = "SnapshotTopComponent";
+
+    private final Result<RangeSliderModel> result;
+    private final RangeSlider rangeSlider;
+    private final ChangedEvent<RangeSliderModel> rangeSliderChangedEvent = new ChangedEvent<RangeSliderModel>(null);
+    private final LookupListener lookupListener = new LookupListener() {
+
+        @Override
+        public void resultChanged(LookupEvent le) {
+            update();
+        }
+    };
+    
+    private final ChangedListener<RangeSliderModel> rangeSliderChangedListener = new ChangedListener<RangeSliderModel>(){
+
+        @Override
+        public void changed(RangeSliderModel source) {
+            rangeSliderChangedEvent.fire();
+        }
+    };
+
+    public SnapshotTopComponent() {
+        initComponents();
+        setName("Snapshot Window");
+        setToolTipText("This is a Snapshot window");
+
+        result = LookupUtils.getLastActiveDelegatingLookup(EditorTopComponent.class).lookupResult(RangeSliderModel.class);
+        result.addLookupListener(lookupListener);
+        this.rangeSlider = new RangeSlider(null);
+        this.setLayout(new BorderLayout());
+        this.add(new JScrollPane(rangeSlider), BorderLayout.CENTER);
+        update();
+    }
+
+    private void update() {
+        RangeSliderModel newModel;
+        if (result.allInstances().size() > 0) {
+            newModel = result.allInstances().iterator().next();
+        } else {
+            newModel = null;
+        }
+        if (rangeSlider.getModel() != null) {
+            rangeSlider.getModel().getChangedEvent().removeListener(rangeSliderChangedListener);
+        }
+        rangeSlider.setModel(newModel);
+        rangeSliderChangedEvent.changeObject(newModel);
+        if (newModel != null) {
+            newModel.getChangedEvent().addListener(rangeSliderChangedListener);
+        }
+    }
+
+    public ChangedEvent<RangeSliderModel> getRangeSliderChangedEvent() {
+        return rangeSliderChangedEvent;
+    }
+
+    public static SnapshotTopComponent findInstance() {
+        return (SnapshotTopComponent) WindowManager.getDefault().findTopComponent(PREFERRED_ID);
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 400, Short.MAX_VALUE)
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 300, Short.MAX_VALUE)
+        );
+    }// </editor-fold>//GEN-END:initComponents
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    // End of variables declaration//GEN-END:variables
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/actions/NextSnapshotAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.snapshots.actions;
+
+import com.oracle.graal.visualizer.snapshots.SnapshotTopComponent;
+import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.util.RangeSliderModel;
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+
+@ActionID(id = "com.oracle.graal.visualizer.editor.actions.NextSnapshotAction", category = "View")
+@ActionRegistration(displayName = "Next snapshot", iconBase = "com/oracle/graal/visualizer/snapshots/images/next_snapshot.png")
+@ActionReference(path = "Menu/View", position = 150)
+public final class NextSnapshotAction extends AbstractAction{
+
+    private RangeSliderModel model;
+
+    public NextSnapshotAction() {
+        SnapshotTopComponent.findInstance().getRangeSliderChangedEvent().addListenerAndFire(changeListener);
+    }
+    private final ChangedListener<RangeSliderModel> changeListener = new ChangedListener<RangeSliderModel>() {
+
+        @Override
+        public void changed(RangeSliderModel source) {
+            model = source;
+            setEnabled(model != null && model.getSecondPosition() != model.getPositions().size() - 1);
+        }
+    };
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        if (model != null) {
+            int fp = model.getFirstPosition();
+            int sp = model.getSecondPosition();
+            if (sp != model.getPositions().size() - 1) {
+                int nfp = fp + 1;
+                int nsp = sp + 1;
+                model.setPositions(nfp, nsp);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/actions/PrevSnapshotAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,66 @@
+/*
+ * 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.oracle.graal.visualizer.snapshots.actions;
+
+import com.oracle.graal.visualizer.snapshots.SnapshotTopComponent;
+import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.util.RangeSliderModel;
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+
+@ActionID(id = "com.oracle.graal.visualizer.editor.actions.PrevSnapshotAction", category = "View")
+@ActionRegistration(displayName = "Previous snapshot", iconBase = "com/oracle/graal/visualizer/snapshots/images/prev_snapshot.png")
+@ActionReference(path = "Menu/View", position = 100)
+public final class PrevSnapshotAction extends AbstractAction {
+
+    private RangeSliderModel model;
+
+    public PrevSnapshotAction() {
+        SnapshotTopComponent.findInstance().getRangeSliderChangedEvent().addListenerAndFire(changeListener);
+    }
+    private final ChangedListener<RangeSliderModel> changeListener = new ChangedListener<RangeSliderModel>() {
+
+        @Override
+        public void changed(RangeSliderModel source) {
+            model = source;
+            setEnabled(model != null && model.getFirstPosition() != 0);
+        }
+    };
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        if (model != null) {
+            int fp = model.getFirstPosition();
+            int sp = model.getSecondPosition();
+            if (fp != 0) {
+                int nfp = fp - 1;
+                int nsp = sp - 1;
+                model.setPositions(nfp, nsp);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/belowExplorerWsmode.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mode version="2.4">
+    <name unique="belowExplorer"/>
+    <kind type="view"/>
+    <state type="joined"/>
+    <constraints>
+        <path orientation="horizontal" number="20" weight="0.3"/>
+        <path orientation="vertical" number="21" weight="0.548"/>
+    </constraints>
+    <bounds x="0" y="0" width="0" height="0"/>
+    <frame state="0"/>
+    
+    <empty-behavior permanent="false"/>
+</mode>
Binary file visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/images/next_snapshot.png has changed
Binary file visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/images/prev_snapshot.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/layer.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
+<filesystem> 
+    <folder name="Windows2">
+        <folder name="Modes">  
+            <file name="belowExplorer.wsmode" url="belowExplorerWsmode.xml"/>
+        </folder>
+    </folder>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.util" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.util.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.util
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/util/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.util-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=a470a16f
+build.xml.script.CRC32=466cf03b
+build.xml.stylesheet.CRC32=05353c81
+# 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=a470a16f
+nbproject/build-impl.xml.script.CRC32=39f45e01
+nbproject/build-impl.xml.stylesheet.CRC32=3f8b4615
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,64 @@
+<?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.util</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>org.netbeans.api.visual</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>2.27.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.48.1</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages>
+                <package>com.oracle.graal.visualizer.util</package>
+                <package>com.sun.hotspot.igv.util</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/oracle/graal/visualizer/util/LookupUtils.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.oracle.graal.visualizer.util;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.Action;
+import org.openide.util.ContextAwareAction;
+import org.openide.util.Lookup;
+import org.openide.util.Lookup.Provider;
+import org.openide.util.lookup.Lookups;
+import org.openide.windows.TopComponent;
+
+/**
+ * Utilities that build upon the Lookup API.
+ */
+public class LookupUtils {
+
+    
+    /**
+     * Creates a new lookup that will delegate to the last open window of a specified top component class. If the window is closed, the lookup will be empty.
+     * @param clazz the class identifying the top component type
+     * @return a delegating lookup
+     */
+    public static Lookup getLastActiveDelegatingLookup(Class<?> clazz) {
+        final TopComponentLookup topComponentLookupImpl = new TopComponentLookup(clazz);
+        TopComponent.getRegistry().addPropertyChangeListener(topComponentLookupImpl);
+        return topComponentLookupImpl.lookup;
+    }
+    
+    public static Iterable<Action> lookupActions(String path) {
+        return lookupActions(path, null);
+    }
+
+    public static Iterable<Action> lookupActions(String path, Lookup context) {
+        List<Action> actions = new ArrayList<>();
+        for (Action a : Lookups.forPath(path).lookupAll(Action.class)) {
+            Action newAction = a;
+            if (a instanceof ContextAwareAction && context != null) {
+                newAction = ((ContextAwareAction) a).createContextAwareInstance(context);
+            }
+            newAction.putValue(Action.SHORT_DESCRIPTION, newAction.getValue(Action.NAME));
+            actions.add(newAction);
+            
+        }
+        return actions;
+    }
+    
+    private static class TopComponentLookup implements PropertyChangeListener {
+        private final Class<?> clazz;
+        private final Lookup lookup;
+        private TopComponent lastActive;
+        
+        private final Provider lookupProvider = new Provider() {
+
+            @Override
+            public Lookup getLookup() {
+                if (lastActive == null) {
+                    return Lookup.EMPTY;
+                } else {
+                    return lastActive.getLookup();
+                }
+            }
+        };
+        
+        public TopComponentLookup(Class<?> clazz) {
+            this.clazz = clazz;
+            lookup = Lookups.proxy(lookupProvider);
+            update();
+        }
+        
+        @Override
+        public void propertyChange(PropertyChangeEvent evt) {
+            update();
+        }
+
+        private void update() {
+            TopComponent curActivated = TopComponent.getRegistry().getActivated();
+            if (curActivated != lastActive) {
+                if (clazz.isAssignableFrom(curActivated.getClass())) {
+                    // We have a new top component for our lookup.
+                    lastActive = curActivated;
+                    refreshLookup();
+                } else {
+                    // We have no new top component. Check if the old one is still opened.
+                    if (lastActive != null && !TopComponent.getRegistry().getOpened().contains(lastActive)) {
+                        // The top component was closed => Remove lookup.
+                        lastActive = null;
+                        refreshLookup();
+                    }
+                }
+            }
+        }
+
+        private void refreshLookup() {
+            lookup.lookup(Object.class);
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/sun/hotspot/igv/util/BoundedZoomAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,180 @@
+/*
+ * 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.util;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Rectangle;
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.action.WidgetAction.State;
+import org.netbeans.api.visual.action.WidgetAction.WidgetMouseWheelEvent;
+import org.netbeans.api.visual.animator.SceneAnimator;
+import org.netbeans.api.visual.widget.Scene;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class BoundedZoomAction extends WidgetAction.Adapter {
+
+    private double minFactor = 0.0;
+    private double maxFactor = Double.MAX_VALUE;
+    private double zoomMultiplier;
+    private boolean useAnimator;
+
+    public BoundedZoomAction(double zoomMultiplier, boolean useAnimator) {
+        this.zoomMultiplier = zoomMultiplier;
+        this.useAnimator = useAnimator;
+    }
+
+    public double getMinFactor() {
+        return minFactor;
+    }
+
+    public void setMinFactor(double d) {
+        minFactor = d;
+    }
+
+    public double getMaxFactor() {
+        return maxFactor;
+    }
+
+    public void setMaxFactor(double d) {
+        maxFactor = d;
+    }
+
+    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 mouseWheelMoved(Widget widget, WidgetMouseWheelEvent event) {
+        final Scene scene = widget.getScene();
+        int amount = event.getWheelRotation();
+        JScrollPane scrollPane = findScrollPane(scene.getView());
+        Point viewPosition = null;
+        Point mouseLocation = scene.convertSceneToView(event.getPoint());
+        int xOffset = 0;
+        int yOffset = 0;
+        Rectangle bounds = new Rectangle(scene.getBounds());
+        Dimension componentSize = new Dimension(scene.getView().getPreferredSize());
+
+        if (scrollPane != null) {
+            viewPosition = new Point(scrollPane.getViewport().getViewPosition());
+            xOffset = (mouseLocation.x - viewPosition.x);
+            yOffset = (mouseLocation.y - viewPosition.y);
+            viewPosition.x += xOffset;
+            viewPosition.y += yOffset;
+        }
+
+        if (useAnimator) {
+            SceneAnimator sceneAnimator = scene.getSceneAnimator();
+            synchronized (sceneAnimator) {
+                double zoom = sceneAnimator.isAnimatingZoomFactor() ? sceneAnimator.getTargetZoomFactor() : scene.getZoomFactor();
+                while (amount > 0 && zoom / zoomMultiplier >= minFactor && zoom / zoomMultiplier <= maxFactor) {
+                    zoom /= zoomMultiplier;
+                    if (viewPosition != null) {
+                        viewPosition.x /= zoomMultiplier;
+                        viewPosition.y /= zoomMultiplier;
+                        bounds.width /= zoomMultiplier;
+                        bounds.height /= zoomMultiplier;
+                        componentSize.width /= zoomMultiplier;
+                        componentSize.height /= zoomMultiplier;
+                    }
+                    amount--;
+                }
+                while (amount < 0 && zoom * zoomMultiplier >= minFactor && zoom * zoomMultiplier <= maxFactor) {
+                    zoom *= zoomMultiplier;
+                    if (viewPosition != null) {
+                        viewPosition.x *= zoomMultiplier;
+                        viewPosition.y *= zoomMultiplier;
+                        bounds.width *= zoomMultiplier;
+                        bounds.height *= zoomMultiplier;
+                        componentSize.width *= zoomMultiplier;
+                        componentSize.height *= zoomMultiplier;
+                    }
+                    amount++;
+                }
+                sceneAnimator.animateZoomFactor(zoom);
+            }
+        } else {
+            double zoom = scene.getZoomFactor();
+            while (amount > 0 && zoom / zoomMultiplier >= minFactor && zoom / zoomMultiplier <= maxFactor) {
+                zoom /= zoomMultiplier;
+                if (viewPosition != null) {
+                    viewPosition.x /= zoomMultiplier;
+                    viewPosition.y /= zoomMultiplier;
+                    bounds.width /= zoomMultiplier;
+                    bounds.height /= zoomMultiplier;
+                    componentSize.width /= zoomMultiplier;
+                    componentSize.height /= zoomMultiplier;
+                }
+                amount--;
+            }
+            while (amount < 0 && zoom * zoomMultiplier >= minFactor && zoom * zoomMultiplier <= maxFactor) {
+                zoom *= zoomMultiplier;
+                if (viewPosition != null) {
+                    viewPosition.x *= zoomMultiplier;
+                    viewPosition.y *= zoomMultiplier;
+                    bounds.width *= zoomMultiplier;
+                    bounds.height *= zoomMultiplier;
+                    componentSize.width *= zoomMultiplier;
+                    componentSize.height *= zoomMultiplier;
+                }
+                amount++;
+            }
+            scene.setZoomFactor(zoom);
+        }
+
+        if (scrollPane != null) {
+            scene.validate(); // Call validate to update size of scene
+            Dimension size = scrollPane.getViewport().getExtentSize();
+            viewPosition.x -= xOffset;
+            viewPosition.y -= yOffset;
+            scene.resolveBounds(scene.getLocation(), bounds);
+            scene.getView().setPreferredSize(componentSize);
+            scene.getView().revalidate();
+            scene.getView().addNotify();
+            scrollPane.getViewport().setViewPosition(viewPosition);
+        }
+
+        return WidgetAction.State.CONSUMED;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/sun/hotspot/igv/util/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Util
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/sun/hotspot/igv/util/ColorIcon.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,58 @@
+/*
+ * 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.util;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import javax.swing.Icon;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ColorIcon implements Icon {
+
+    private Color color;
+
+    public ColorIcon(Color c) {
+        color = c;
+    }
+
+    @Override
+    public void paintIcon(Component c, Graphics g, int x, int y) {
+        g.setColor(color);
+        g.fillRect(x, y, 16, 16);
+    }
+
+    @Override
+    public int getIconWidth() {
+        return 16;
+    }
+
+    @Override
+    public int getIconHeight() {
+        return 16;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/sun/hotspot/igv/util/CompilationViewModel.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,47 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.sun.hotspot.igv.util;
+
+import com.sun.hotspot.igv.data.*;
+import java.awt.Color;
+import java.util.List;
+
+public class CompilationViewModel implements ChangedEventProvider<CompilationViewModel> {
+    
+    private final ChangedEvent<CompilationViewModel> changedEvent = new ChangedEvent<>(this);
+    private final RangeSliderModel model;
+    private final Group group;
+
+    @Override
+    public ChangedEvent<CompilationViewModel> getChangedEvent() {
+        return changedEvent;
+    }
+    
+    public CompilationViewModel(RangeSliderModel model, Group group) {
+        this.model = model;
+        this.group = group;
+        model.getChangedEvent().addListener(rangeSliderChangedListener);
+    }
+    
+    private final ChangedListener<RangeSliderModel> rangeSliderChangedListener = new ChangedListener<RangeSliderModel>() {
+        @Override
+        public void changed(RangeSliderModel source) {
+            changedEvent.fire();
+        }
+    };
+    
+    public InputGraph getFirstSnapshot() {
+        return group.getGraphs().get(model.getFirstPosition());
+    }
+    
+    public InputGraph getSecondSnapshot() {
+        return group.getGraphs().get(model.getSecondPosition());
+    }
+
+    public void setColors(List<Color> colors) {
+        model.setColors(colors);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,49 @@
+/*
+ * 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.util;
+
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class DoubleClickAction extends WidgetAction.Adapter {
+
+    private DoubleClickHandler handler;
+
+    public DoubleClickAction(DoubleClickHandler handler) {
+        this.handler = handler;
+    }
+
+    @Override
+    public WidgetAction.State mouseClicked(Widget widget, WidgetAction.WidgetMouseEvent event) {
+        if (event.getClickCount() > 1) {
+            handler.handleDoubleClick(widget, event);
+            return WidgetAction.State.CONSUMED;
+        }
+        return WidgetAction.State.REJECTED;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickHandler.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,36 @@
+/*
+ * 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.util;
+
+import org.netbeans.api.visual.action.WidgetAction.WidgetMouseEvent;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface DoubleClickHandler {
+
+    public void handleDoubleClick(Widget w, WidgetMouseEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSatelliteComponent.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,208 @@
+/*
+ * 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.util;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.JComponent;
+import org.netbeans.api.visual.widget.Scene;
+
+/**
+ * @author David Kaspar
+ * @author Thomas Wuerthinger
+ */
+public class ExtendedSatelliteComponent extends JComponent implements MouseListener, MouseMotionListener, Scene.SceneListener, ComponentListener {
+
+    private Scene scene;
+    private Image image;
+    private int imageWidth;
+    private int imageHeight;
+
+    public ExtendedSatelliteComponent(Scene scene) {
+        this.scene = scene;
+        setDoubleBuffered(true);
+        setPreferredSize(new Dimension(128, 128));
+        addMouseListener(this);
+        addMouseMotionListener(this);
+    }
+
+    @Override
+    public void addNotify() {
+        super.addNotify();
+        scene.addSceneListener(this);
+        JComponent viewComponent = scene.getView();
+        if (viewComponent == null) {
+            viewComponent = scene.createView();
+        }
+        viewComponent.addComponentListener(this);
+        repaint();
+    }
+
+    @Override
+    public void removeNotify() {
+        scene.getView().removeComponentListener(this);
+        scene.removeSceneListener(this);
+        super.removeNotify();
+    }
+
+    public void update() {
+        this.image = null;
+        repaint();
+    }
+
+    @Override
+    public void paint(Graphics g) {
+        Graphics2D gr = (Graphics2D) g;
+        super.paint(g);
+        Rectangle bounds = scene.getBounds();
+        Dimension size = getSize();
+
+        double sx = bounds.width > 0 ? (double) size.width / bounds.width : 0.0;
+        double sy = bounds.width > 0 ? (double) size.height / bounds.height : 0.0;
+        double scale = Math.min(sx, sy);
+
+        int vw = (int) (scale * bounds.width);
+        int vh = (int) (scale * bounds.height);
+        int vx = (size.width - vw) / 2;
+        int vy = (size.height - vh) / 2;
+
+
+        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.paint(ig);
+        }
+
+        gr.drawImage(image, vx, vy, this);
+
+        JComponent component = scene.getView();
+        double zoomFactor = scene.getZoomFactor();
+        Rectangle viewRectangle = component != null ? component.getVisibleRect() : null;
+        if (viewRectangle != null) {
+            Rectangle window = new Rectangle(
+                    (int) ((double) viewRectangle.x * scale / zoomFactor),
+                    (int) ((double) viewRectangle.y * scale / zoomFactor),
+                    (int) ((double) viewRectangle.width * scale / zoomFactor),
+                    (int) ((double) viewRectangle.height * scale / zoomFactor));
+            window.translate(vx, vy);
+            gr.setColor(new Color(200, 200, 200, 128));
+            gr.fill(window);
+            gr.setColor(Color.BLACK);
+            gr.drawRect(window.x, window.y, window.width - 1, window.height - 1);
+        }
+    }
+
+    @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) {
+    }
+
+    private void moveVisibleRect(Point center) {
+        JComponent component = scene.getView();
+        if (component == null) {
+            return;
+        }
+        double zoomFactor = scene.getZoomFactor();
+        Rectangle bounds = scene.getBounds();
+        Dimension size = getSize();
+
+        double sx = bounds.width > 0 ? (double) size.width / bounds.width : 0.0;
+        double sy = bounds.width > 0 ? (double) size.height / bounds.height : 0.0;
+        double scale = Math.min(sx, sy);
+
+        int vw = (int) (scale * bounds.width);
+        int vh = (int) (scale * bounds.height);
+        int vx = (size.width - vw) / 2;
+        int vy = (size.height - vh) / 2;
+
+        int cx = (int) ((double) (center.x - vx) / scale * zoomFactor);
+        int cy = (int) ((double) (center.y - vy) / scale * zoomFactor);
+
+        Rectangle visibleRect = component.getVisibleRect();
+        visibleRect.x = cx - visibleRect.width / 2;
+        visibleRect.y = cy - visibleRect.height / 2;
+        component.scrollRectToVisible(visibleRect);
+
+    }
+
+    @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) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSelectAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,69 @@
+/*
+ * 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.util;
+
+import java.awt.event.MouseEvent;
+import javax.swing.JPanel;
+import org.netbeans.api.visual.action.ActionFactory;
+import org.netbeans.api.visual.action.SelectProvider;
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.action.WidgetAction.State;
+import org.netbeans.api.visual.action.WidgetAction.WidgetKeyEvent;
+import org.netbeans.api.visual.action.WidgetAction.WidgetMouseEvent;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ExtendedSelectAction extends WidgetAction.Adapter {
+
+    private WidgetAction innerAction;
+    private JPanel panel;
+
+    public ExtendedSelectAction(SelectProvider provider) {
+        innerAction = ActionFactory.createSelectAction(provider);
+        panel = new JPanel();
+    }
+
+    @Override
+    public State mousePressed(Widget widget, WidgetMouseEvent event) {
+        // TODO: Solve this differently?
+        if (event.getButton() != MouseEvent.BUTTON2) {
+            return innerAction.mousePressed(widget, new WidgetMouseEvent(event.getEventID(), new MouseEvent(panel, (int) event.getEventID(), event.getWhen(), event.getModifiersEx(), event.getPoint().x, event.getPoint().y, event.getClickCount(), event.isPopupTrigger(), MouseEvent.BUTTON1)));
+        } else {
+            return super.mousePressed(widget, event);
+        }
+    }
+
+    @Override
+    public State mouseReleased(Widget widget, WidgetMouseEvent event) {
+        return innerAction.mouseReleased(widget, event);
+    }
+
+    @Override
+    public State keyTyped(Widget widget, WidgetKeyEvent event) {
+        return innerAction.keyTyped(widget, event);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1998, 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.  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.util;
+
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Property;
+import java.lang.reflect.InvocationTargetException;
+import org.openide.nodes.Node;
+import org.openide.nodes.Sheet;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class PropertiesSheet {
+
+    public static void initializeSheet(final Properties properties, Sheet s) {
+
+        Sheet.Set set1 = Sheet.createPropertiesSet();
+        set1.setDisplayName("Properties");
+        for (final Property p : properties) {
+            Node.Property<String> prop = new Node.Property<String>(String.class) {
+
+                @Override
+                public boolean canRead() {
+                    return true;
+                }
+
+                @Override
+                public String getValue() throws IllegalAccessException, InvocationTargetException {
+                    return p.getValue();
+                }
+
+                @Override
+                public boolean canWrite() {
+                    return false;
+                }
+
+                @Override
+                public void setValue(String arg0) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+                    properties.setProperty(p.getName(), arg0);
+                }
+            };
+            prop.setName(p.getName());
+            set1.put(prop);
+        }
+        s.put(set1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.util;
+
+import com.sun.hotspot.igv.data.ChangedListener;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.util.List;
+import javax.swing.JComponent;
+
+public final class RangeSlider extends JComponent {
+
+    public static final int BAR_THICKNESS = 2;
+    public static final int BAR_CIRCLE_SIZE = 9;
+    public static final int MOUSE_ENDING_OFFSET = 3;
+    public static final Color BACKGROUND_COLOR = Color.white;
+    public static final Color BAR_COLOR = Color.black;
+    public static final Color BAR_SELECTION_COLOR = new Color(255, 0, 0, 120);
+    public static final Color TEXT_SELECTION_COLOR = new Color(200, 200, 200, 255);
+    public static final int ITEM_HEIGHT = 30;
+    public static final int ITEM_WIDTH = 30;
+    private RangeSliderModel model;
+    private Point startPoint;
+    private RangeSliderModel tempModel;
+    private Point lastMouseMove;
+
+    public RangeSlider(RangeSliderModel newModel) {
+        this.addMouseMotionListener(mouseMotionListener);
+        this.addMouseListener(mouseListener);
+        setModel(newModel);
+    }
+
+    private RangeSliderModel getPaintingModel() {
+        if (tempModel != null) {
+            return tempModel;
+        }
+        return model;
+    }
+
+    @Override
+    public Dimension getPreferredSize() {
+        if (getPaintingModel() != null) {
+            Graphics g = this.getGraphics();
+            int maxWidth = 0;
+            List<String> list = getPaintingModel().getPositions();
+            for (int i = 0; i < list.size(); i++) {
+                String curS = list.get(i);
+                if (curS != null && curS.length() > 0) {
+                    FontMetrics metrics = g.getFontMetrics();
+                    Rectangle bounds = metrics.getStringBounds(curS, g).getBounds();
+                    maxWidth = Math.max(maxWidth, (int) bounds.getWidth());
+                }
+            }
+            return new Dimension(maxWidth + ITEM_WIDTH, ITEM_HEIGHT * list.size());
+        }
+        return super.getPreferredSize();
+    }
+    private ChangedListener<RangeSliderModel> modelChangedListener = new ChangedListener<RangeSliderModel>() {
+
+        @Override
+        public void changed(RangeSliderModel source) {
+            update();
+        }
+    };
+
+    private void update() {
+        this.repaint();
+    }
+
+    private Rectangle getItemBounds(int index) {
+        Rectangle r = new Rectangle();
+        r.width = ITEM_WIDTH;
+        r.height = ITEM_HEIGHT;
+        r.x = 0;
+        r.y = ITEM_HEIGHT * index;
+        return r;
+    }
+
+    @Override
+    public void paint(Graphics g) {
+        super.paint(g);
+        Graphics2D g2 = (Graphics2D) g;
+        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON);
+        int width = getWidth();
+        int height = getHeight();
+
+        g2.setColor(BACKGROUND_COLOR);
+        g2.fillRect(0, 0, width, height);
+
+        // Nothing to paint?
+        if (getPaintingModel() == null || getPaintingModel().getPositions().isEmpty()) {
+            return;
+        }
+
+        paintSelected(g2);
+        paintBar(g2);
+
+    }
+
+    private void fillRect(Graphics2D g, int startX, int startY, int endY, int thickness) {
+        g.fillRect(startX - thickness / 2, startY, thickness, endY - startY);
+    }
+
+    private void paintBar(Graphics2D g) {
+        List<String> list = getPaintingModel().getPositions();
+
+        g.setColor(BAR_COLOR);
+        Rectangle firstItemBounds = getItemBounds(0);
+        Rectangle lastItemBounds = getItemBounds(list.size() - 1);
+        fillRect(g, (int) firstItemBounds.getCenterX(), (int) firstItemBounds.getCenterY(), (int) lastItemBounds.getCenterY(), BAR_THICKNESS);
+
+        for (int i = 0; i < list.size(); i++) {
+            Rectangle curItemBounds = getItemBounds(i);
+            g.setColor(getPaintingModel().getColors().get(i));
+            g.fillOval((int) curItemBounds.getCenterX() - BAR_CIRCLE_SIZE / 2, (int) curItemBounds.getCenterY() - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE);
+            g.setColor(Color.black);
+            g.drawOval((int) curItemBounds.getCenterX() - BAR_CIRCLE_SIZE / 2, (int) curItemBounds.getCenterY() - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE);
+
+            String curS = list.get(i);
+            if (curS != null && curS.length() > 0) {
+                FontMetrics metrics = g.getFontMetrics();
+                Rectangle bounds = metrics.getStringBounds(curS, g).getBounds();
+                g.setColor(Color.black);
+                g.drawString(curS, curItemBounds.x + curItemBounds.width, (int) curItemBounds.getCenterY() + bounds.height / 2 - 2);
+            }
+        }
+
+    }
+
+    private void paintSelected(Graphics2D g) {
+        List<String> list = getPaintingModel().getPositions();
+        for (int i = 0; i < list.size(); i++) {
+            Rectangle curItemBounds = getItemBounds(i);
+            if (lastMouseMove != null && curItemBounds.y <= lastMouseMove.y && curItemBounds.y + curItemBounds.height > lastMouseMove.y) {
+                g.setColor(TEXT_SELECTION_COLOR);
+                g.fillRect(0, curItemBounds.y, getWidth(), curItemBounds.height);
+            }
+        }
+        final Rectangle barBounds = getBarBounds();
+
+        g.setColor(BAR_SELECTION_COLOR);
+        g.fill(barBounds);
+    }
+
+    private Rectangle getBarBounds() {
+        final Rectangle startItemBounds = getItemBounds(getPaintingModel().getFirstPosition());
+        final Rectangle endItemBounds = getItemBounds(getPaintingModel().getSecondPosition());
+        int startY = startItemBounds.y;
+        int endY = endItemBounds.y + endItemBounds.height;
+        return new Rectangle(0, startY, getWidth(), endY - startY);
+    }
+
+    private int getIndexFromPosition(int y) {
+        for (int i = 0; i < getPaintingModel().getPositions().size() - 1; i++) {
+            Rectangle bounds = getItemBounds(i);
+            if (bounds.y <= y && bounds.y + bounds.height >= y) {
+                return i;
+            }
+        }
+        return getPaintingModel().getPositions().size() - 1;
+    }
+    private final MouseMotionListener mouseMotionListener = new MouseMotionListener() {
+
+        @Override
+        public void mouseDragged(MouseEvent e) {
+            if (startPoint != null) {
+                int startIndex = getIndexFromPosition(startPoint.y);
+                int curIndex = getIndexFromPosition(e.getPoint().y);
+                tempModel.setPositions(startIndex, curIndex);
+            }
+        }
+
+        @Override
+        public void mouseMoved(MouseEvent e) {
+            lastMouseMove = e.getPoint();
+            update();
+        }
+    };
+    private final MouseListener mouseListener = new MouseListener() {
+
+        @Override
+        public void mouseClicked(MouseEvent e) {
+            if (model != null) {
+                int index = getIndexFromPosition(e.getPoint().y);
+                model.setPositions(index, index);
+            }
+        }
+
+        @Override
+        public void mousePressed(MouseEvent e) {
+            if (model != null) {
+                int index = getIndexFromPosition(e.getPoint().y);
+                startPoint = e.getPoint();
+                tempModel = model.copy();
+                tempModel.getChangedEvent().addListener(modelChangedListener);
+                tempModel.setPositions(index, index);
+            }
+        }
+
+        @Override
+        public void mouseReleased(MouseEvent e) {
+            if (tempModel != null) {
+                model.setPositions(tempModel.getFirstPosition(), tempModel.getSecondPosition());
+                tempModel = null;
+                startPoint = null;
+            }
+        }
+
+        @Override
+        public void mouseEntered(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseExited(MouseEvent e) {
+            lastMouseMove = null;
+            repaint();
+        }
+    };
+
+    public RangeSliderModel getModel() {
+        return model;
+    }
+
+    public void setModel(RangeSliderModel newModel) {
+        if (newModel != this.model) {
+            if (this.model != null) {
+                this.model.getChangedEvent().removeListener(modelChangedListener);
+            }
+            this.model = newModel;
+            if (newModel != null) {
+                newModel.getChangedEvent().addListener(modelChangedListener);
+            }
+            this.tempModel = null;
+            update();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 1998, 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.  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.util;
+
+import com.sun.hotspot.igv.data.ChangedEvent;
+import com.sun.hotspot.igv.data.ChangedEventProvider;
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class RangeSliderModel implements ChangedEventProvider<RangeSliderModel> {
+
+    // Warning: Update setData method if fields are added
+    private ChangedEvent<RangeSliderModel> changedEvent;
+    private List<String> positions;
+    private int firstPosition;
+    private int secondPosition;
+    private List<Color> colors;
+
+    public void setData(RangeSliderModel model) {
+        boolean changed = false;
+        changed |= (positions != model.positions);
+        positions = model.positions;
+        changed |= (firstPosition != model.firstPosition);
+        firstPosition = model.firstPosition;
+        changed |= (secondPosition != model.secondPosition);
+        secondPosition = model.secondPosition;
+        changed |= (colors != model.colors);
+        colors = model.colors;
+        if (changed) {
+            changedEvent.fire();
+        }
+    }
+
+    public RangeSliderModel(List<String> positions) {
+        assert positions.size() > 0;
+        this.changedEvent = new ChangedEvent<>(this);
+        setPositions(positions);
+    }
+
+    protected final void setPositions(List<String> positions) {
+        this.positions = positions;
+        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();
+    }
+
+    public void setColors(List<Color> colors) {
+        this.colors = colors;
+        changedEvent.fire();
+    }
+
+    public List<Color> getColors() {
+        return colors;
+    }
+
+    public RangeSliderModel copy() {
+        RangeSliderModel newModel = new RangeSliderModel(positions);
+        newModel.setData(this);
+        return newModel;
+    }
+
+    public List<String> getPositions() {
+        return Collections.unmodifiableList(positions);
+    }
+
+    public int getFirstPosition() {
+        return firstPosition;
+    }
+
+    public int getSecondPosition() {
+        return secondPosition;
+    }
+
+    public void setPositions(int fp, int sp) {
+        assert fp >= 0 && fp < positions.size();
+        assert sp >= 0 && sp < positions.size();
+        firstPosition = fp;
+        secondPosition = sp;
+        ensureOrder();
+        changedEvent.fire();
+    }
+
+    private void ensureOrder() {
+        if (secondPosition < firstPosition) {
+            int tmp = secondPosition;
+            secondPosition = firstPosition;
+            firstPosition = tmp;
+        }
+    }
+
+    @Override
+    public ChangedEvent<RangeSliderModel> getChangedEvent() {
+        return changedEvent;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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.view" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.view.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/manifest.mf	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.view
+OpenIDE-Module-Layer: com/sun/hotspot/igv/view/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/view/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.view-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=2de95ef6
+build.xml.script.CRC32=31afe4b1
+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=2de95ef6
+nbproject/build-impl.xml.script.CRC32=fa7a4119
+nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,183 @@
+<?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.view</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.oracle.graal.visualizer.editor</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.oracle.graal.visualizer.sharedactions</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.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>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.hierarchicallayout</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.layout</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.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.svg</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.visual</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <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>
+                    <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.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>
+                <package>com.sun.hotspot.igv.view</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/nbproject/suite.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+com.sun.hotspot.igv.view.scene.GraphCompilationViewerFactory
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=View
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,4 @@
+CTL_EditorAction=Open Editor Window
+CTL_EnableBlockLayoutAction=Enable block layout
+CTL_NodeFindAction=Find
+CTL_ExportAction=Export current graph...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandPredecessorsAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,63 @@
+/*
+ * 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.oracle.graal.visualizer.editor.EditorTopComponent;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.CallableSystemAction;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class ExpandPredecessorsAction extends CallableSystemAction {
+
+    @Override
+    public void performAction() {
+        EditorTopComponent editor = EditorTopComponent.getActive();
+        if (editor != null) {
+            //editor.expandPredecessors();
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "Expand Above";
+    }
+
+    @Override
+    protected void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandSuccessorsAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,63 @@
+/*
+ * 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.oracle.graal.visualizer.editor.EditorTopComponent;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.CallableSystemAction;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class ExpandSuccessorsAction extends CallableSystemAction {
+
+    @Override
+    public void performAction() {
+        EditorTopComponent editor = EditorTopComponent.getActive();
+        if (editor != null) {
+            //editor.expandSuccessors();
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "Expand Below";
+    }
+
+    @Override
+    protected void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/ExtractAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,83 @@
+/*
+ * 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.oracle.graal.visualizer.editor.EditorTopComponent;
+import java.awt.Event;
+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.ActionRegistration;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.CallableSystemAction;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+@ActionID(id = "com.sun.hotspot.igv.view.actions.ExtractAction", category = "View")
+@ActionRegistration(displayName = "Extract nodes")
+@ActionReference(path = "Menu/View", position = 300)
+public final class ExtractAction extends CallableSystemAction {
+
+    @Override
+    public void performAction() {
+        EditorTopComponent editor = EditorTopComponent.getActive();
+        if (editor != null) {
+            //editor.extract();
+        }
+    }
+
+    public ExtractAction() {
+        putValue(Action.SHORT_DESCRIPTION, "Extract current set of selected nodes");
+        putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X, Event.CTRL_MASK, false));
+    }
+
+    @Override
+    public String getName() {
+        return "Extract action";
+    }
+
+    @Override
+    protected void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+
+    @Override
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/view/images/extract.gif";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/HideAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,83 @@
+/*
+ * 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.oracle.graal.visualizer.editor.EditorTopComponent;
+import java.awt.Event;
+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.ActionRegistration;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.CallableSystemAction;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+@ActionID(id = "com.sun.hotspot.igv.view.actions.HideAction", category = "View")
+@ActionRegistration(displayName = "Hide nodes")
+@ActionReference(path = "Menu/View", position = 400)
+public final class HideAction extends CallableSystemAction {
+
+    @Override
+    public void performAction() {
+        EditorTopComponent editor = EditorTopComponent.getActive();
+        if (editor != null) {
+            //editor.hideNodes();
+        }
+    }
+
+    public HideAction() {
+        putValue(Action.SHORT_DESCRIPTION, "Hide selected nodes");
+        putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_H, Event.CTRL_MASK, false));
+    }
+
+    @Override
+    public String getName() {
+        return "Hide";
+    }
+
+    @Override
+    protected void initialize() {
+        super.initialize();
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+
+    @Override
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/view/images/hide.gif";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/MouseOverAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,59 @@
+/*
+ * 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 org.netbeans.api.visual.action.HoverProvider;
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.action.WidgetAction.State;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class MouseOverAction extends WidgetAction.Adapter {
+
+    private long eventID = Integer.MIN_VALUE;
+    private HoverProvider provider;
+
+    public MouseOverAction(HoverProvider provider) {
+        this.provider = provider;
+    }
+
+    @Override
+    public State mouseMoved(Widget widget, WidgetMouseEvent event) {
+        long id = event.getEventID();
+        if (id != eventID) {
+            eventID = id;
+            provider.widgetHovered(widget);
+        }
+        return State.REJECTED;
+    }
+
+    @Override
+    public State mouseExited(Widget widget, WidgetMouseEvent event) {
+        provider.widgetHovered(null);
+        return State.REJECTED;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/PredSuccAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,57 @@
+/*
+ * 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 java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.ImageIcon;
+import org.openide.util.ImageUtilities;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class PredSuccAction extends AbstractAction {
+
+    private boolean state;
+    public static final String STATE = "state";
+
+    public PredSuccAction() {
+        state = true;
+        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);
+    }
+
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/view/images/predsucc.gif";
+    }
+}
Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/blocks.gif has changed
Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/expand.gif has changed
Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/extract.gif has changed
Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/hide.gif has changed
Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/overview.png has changed
Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/pan_mode.png has changed
Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/predsucc.gif has changed
Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/selection_mode.png has changed
Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/zoom_in.png has changed
Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/zoom_out.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/layer.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,22 @@
+<?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="CompilationViewer">
+        <folder name="Graph">
+            <folder name="Actions">
+                <file name="com-oracle-graal-visualizer-sharedactions-ShowAllAction.shadow">
+                    <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ShowAllAction.instance"/>
+                </file>
+                <file name="com-oracle-graal-visualizer-sharedactions-ZoomInAction.shadow">
+                    <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ZoomInAction.instance"/>
+                </file>
+                <file name="com-oracle-graal-visualizer-sharedactions-ZoomOutAction.shadow">
+                    <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ZoomOutAction.instance"/>
+                </file>
+                <file name="com-oracle-graal-visualizer-sharedactions-ExportSVGAction.shadow">
+                    <attr name="originalFile" stringvalue="Actions/File/com-oracle-graal-visualizer-sharedactions-ExportSVGAction.instance"/>
+                </file>
+            </folder>
+        </folder>
+    </folder>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/scene/CustomizablePanWidgetAction.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,146 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2010 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.scene;
+
+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 CustomizablePanWidgetAction 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 CustomizablePanWidgetAction(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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/scene/DiagramScene.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,964 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.scene;
+
+import com.oracle.graal.visualizer.editor.DiagramViewModel;
+import com.oracle.graal.visualizer.sharedactions.ExportSVGCookie;
+import com.oracle.graal.visualizer.sharedactions.ZoomCookie;
+import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.data.Pair;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.graph.*;
+import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager;
+import com.sun.hotspot.igv.layout.LayoutGraph;
+import com.sun.hotspot.igv.util.ColorIcon;
+import com.sun.hotspot.igv.util.DoubleClickAction;
+import com.sun.hotspot.igv.util.PropertiesSheet;
+import com.sun.hotspot.igv.view.widgets.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.List;
+import java.util.*;
+import javax.swing.*;
+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.model.*;
+import org.netbeans.api.visual.widget.LayerWidget;
+import org.netbeans.api.visual.widget.Widget;
+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;
+
+public class DiagramScene extends ObjectScene implements ExportSVGCookie, ZoomCookie {
+
+    private CustomizablePanWidgetAction panAction;
+    private WidgetAction hoverAction;
+    private WidgetAction selectAction;
+    private Lookup lookup;
+    private InstanceContent content;
+    private Action[] actions;
+    private LayerWidget connectionLayer;
+    private JScrollPane scrollPane;
+    private LayerWidget mainLayer;
+    private LayerWidget blockLayer;
+    private Widget topLeft;
+    private Widget bottomRight;
+    private DiagramViewModel model;
+    private WidgetAction zoomAction;
+    private boolean rebuilding;
+    /**
+     * The alpha level of partially visible figures.
+     */
+    public static final float ALPHA = 0.4f;
+    /**
+     * 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 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));
+            widget.setForeground(Color.red);
+            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;
+    }
+
+    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)));
+        }
+    }
+
+    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)));
+        }
+    }
+
+    private void centerFigures(Collection<Figure> list) {
+        gotoFigures(list);
+    }
+
+    private RectangularSelectProvider rectangularSelectProvider = new RectangularSelectProvider() {
+
+        @Override
+        public void performSelection(Rectangle rectangle) {
+            if (rectangle.width < 0) {
+                rectangle.x += rectangle.width;
+                rectangle.width *= -1;
+            }
+
+            if (rectangle.height < 0) {
+                rectangle.y += rectangle.height;
+                rectangle.height *= -1;
+            }
+
+            Set<Object> selectedObjects = new HashSet<>();
+            for (Figure f : getModel().getDiagramToView().getFigures()) {
+                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 {
+                    assert false : "w should not be null here!";
+                }
+            }
+
+            setSelectedObjects(selectedObjects);
+        }
+    };
+    private MouseWheelListener mouseWheelListener = new MouseWheelListener() {
+
+        @Override
+        public void mouseWheelMoved(MouseWheelEvent e) {
+            if (e.isControlDown()) {
+                DiagramScene.this.relayoutWithoutLayout(null);
+            }
+        }
+    };
+
+    public Point getScrollPosition() {
+        return getScrollPane().getViewport().getViewPosition();
+    }
+
+    public void setScrollPosition(Point p) {
+        getScrollPane().getViewport().setViewPosition(p);
+    }
+
+    private JScrollPane createScrollPane() {
+        JComponent comp = this.createView();
+        comp.setDoubleBuffered(true);
+        comp.setBackground(Color.WHITE);
+        comp.setOpaque(true);
+        this.setBackground(Color.WHITE);
+        this.setOpaque(true);
+        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);
+        }
+
+        @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(b);
+            validate();
+        }
+
+        @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 void setActions(Action[] actions) {
+        this.actions = actions;
+    }
+    
+    
+
+    public DiagramScene(DiagramViewModel model) {
+
+        this.model = model;
+        content = new InstanceContent();
+        lookup = new AbstractLookup(content);
+        content.add(this);
+
+        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 CustomizablePanWidgetAction(~0, MouseEvent.BUTTON1_DOWN_MASK);
+        this.getActions().addAction(panAction);
+
+        selectAction = createSelectAction();
+        this.getActions().addAction(selectAction);
+
+        blockLayer = new LayerWidget(this);
+        this.addChild(blockLayer);
+
+        mainLayer = new LayerWidget(this);
+        this.addChild(mainLayer);
+
+        topLeft = new Widget(this);
+        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);
+
+        connectionLayer = new LayerWidget(this);
+        this.addChild(connectionLayer);
+
+        LayerWidget selectionLayer = new LayerWidget(this);
+        this.addChild(selectionLayer);
+
+        this.setLayout(LayoutFactory.createAbsoluteLayout());
+
+        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));
+
+        this.addObjectSceneListener(selectionChangedListener, ObjectSceneEventType.OBJECT_SELECTION_CHANGED, ObjectSceneEventType.OBJECT_HIGHLIGHTING_CHANGED, ObjectSceneEventType.OBJECT_HOVER_CHANGED);
+        
+        update();
+    }
+
+    public DiagramViewModel getModel() {
+        return model;
+    }
+
+    public JScrollPane getScrollPane() {
+        return scrollPane;
+    }
+
+    Component getComponent() {
+        return scrollPane;
+    }
+
+    public boolean isAllVisible() {
+        return getModel().getHiddenNodes().isEmpty();
+    }
+
+    public Action createGotoAction(final Figure f) {
+        final DiagramScene diagramScene = this;
+        Action a = new AbstractAction() {
+
+            @Override
+            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 += " (";
+
+        if (!this.getWidget(f, FigureWidget.class).isVisible()) {
+            name += "hidden";
+        }
+        name += ")";
+        a.putValue(Action.NAME, name);
+        return a;
+    }
+
+    private void update() {
+        mainLayer.removeChildren();
+        blockLayer.removeChildren();
+
+        rebuilding = true;
+
+        Collection<Object> objects = new ArrayList<>(this.getObjects());
+        for (Object o : objects) {
+            this.removeObject(o);
+        }
+
+        Diagram d = getModel().getDiagramToView();
+
+        for (Figure f : d.getFigures()) {
+            FigureWidget w = new FigureWidget(f, hoverAction, selectAction, this, mainLayer);
+            w.getActions().addAction(ActionFactory.createPopupMenuAction(w));
+            w.getActions().addAction(selectAction);
+            w.getActions().addAction(hoverAction);
+            w.setVisible(false);
+
+            this.addObject(f, w);
+
+            for (InputSlot s : f.getInputSlots()) {
+                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, w, w);
+                addObject(s, sw);
+                sw.getActions().addAction(new DoubleClickAction(sw));
+                sw.getActions().addAction(hoverAction);
+                sw.getActions().addAction(selectAction);
+            }
+        }
+
+        rebuilding = false;
+        this.smallUpdate(true);
+    }
+
+    public boolean isRebuilding() {
+        return rebuilding;
+    }
+
+    private void smallUpdate(boolean relayout) {
+
+        this.updateHiddenNodes(model.getHiddenNodes(), relayout);
+        this.validate();
+    }
+
+    private boolean isVisible(Connection c) {
+        FigureWidget w1 = getWidget(c.getInputSlot().getFigure());
+        FigureWidget w2 = getWidget(c.getOutputSlot().getFigure());
+
+        if (w1.isVisible() && w2.isVisible()) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private void relayout(Set<Widget> oldVisibleWidgets) {
+        System.out.println("relayout called with old visible widgets: " + oldVisibleWidgets);
+
+        Diagram diagram = getModel().getDiagramToView();
+
+        HashSet<Figure> figures = new HashSet<>();
+
+        for (Figure f : diagram.getFigures()) {
+            FigureWidget w = getWidget(f);
+            if (w.isVisible()) {
+                figures.add(f);
+            }
+        }
+
+        HashSet<Connection> edges = new HashSet<>();
+
+        for (Connection c : diagram.getConnections()) {
+            if (isVisible(c)) {
+                edges.add(c);
+            }
+        }
+
+        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) {
+
+        System.out.println("relayout without layout with visible widgets: " + oldVisibleWidgets);
+
+        Diagram diagram = getModel().getDiagramToView();
+
+        int maxX = -BORDER_SIZE;
+        int maxY = -BORDER_SIZE;
+        for (Figure f : diagram.getFigures()) {
+            FigureWidget w = getWidget(f);
+            if (w.isVisible()) {
+                Point p = f.getPosition();
+                Dimension d = f.getSize();
+                maxX = Math.max(maxX, p.x + d.width);
+                maxY = Math.max(maxY, p.y + d.height);
+            }
+        }
+
+        for (Connection c : diagram.getConnections()) {
+            List<Point> points = c.getControlPoints();
+            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) {
+                        maxX = Math.max(maxX, p.x);
+                        maxY = Math.max(maxY, p.y);
+                    }
+                }
+            }
+        }
+
+        bottomRight.setPreferredLocation(new Point(maxX + BORDER_SIZE, maxY + BORDER_SIZE));
+        int offx = 0;
+        int offy = 0;
+        int curWidth = maxX + 2 * BORDER_SIZE;
+        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;
+        }
+
+        if (curHeight < bounds.height) {
+            offy = (bounds.height - curHeight) / 2;
+        }
+
+        final int offx2 = offx;
+        final int offy2 = offy;
+
+        SceneAnimator animator = this.getSceneAnimator();
+        connectionLayer.removeChildren();
+        int visibleFigureCount = 0;
+        for (Figure f : diagram.getFigures()) {
+            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()) {
+            FigureWidget w = getWidget(f);
+            if (w.isVisible()) {
+                Point p = f.getPosition();
+                Point p2 = new Point(p.x + offx2, p.y + offy2);
+                if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) {
+                    animator.animatePreferredLocation(w, p2);
+                } else {
+                    w.setPreferredLocation(p2);
+                    animator.animatePreferredLocation(w, p2);
+                }
+            }
+        }
+
+        this.validate();
+    }
+    private final Point specialNullPoint = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
+
+    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) {
+
+            if (!isVisible(c)) {
+                continue;
+            }
+
+            List<Point> controlPoints = c.getControlPoints();
+            if (controlPointIndex >= controlPoints.size()) {
+                continue;
+            }
+
+            Point cur = controlPoints.get(controlPointIndex);
+            if (cur == null) {
+                cur = specialNullPoint;
+            } else if (controlPointIndex == 0 && !s.shouldShowName()) {
+                cur = new Point(cur.x, cur.y - SLOT_OFFSET);
+            } else if (controlPointIndex == controlPoints.size() - 1 && !c.getInputSlot().shouldShowName()) {
+                cur = new Point(cur.x, cur.y + SLOT_OFFSET);
+            }
+
+            if (pointMap.containsKey(cur)) {
+                pointMap.get(cur).add(c);
+            } else {
+                List<Connection> newList = new ArrayList<>(2);
+                newList.add(c);
+                pointMap.put(cur, newList);
+            }
+
+        }
+
+        for (Point p : pointMap.keySet()) {
+            List<Connection> connectionList = pointMap.get(p);
+
+            boolean isBold = false;
+            boolean isDashed = true;
+
+            for (Connection c : connectionList) {
+
+                if (c.getStyle() == Connection.ConnectionStyle.BOLD) {
+                    isBold = true;
+                }
+
+                if (c.getStyle() != Connection.ConnectionStyle.DASHED) {
+                    isDashed = false;
+                }
+            }
+
+            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);
+
+                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);
+                w.getActions().addAction(hoverAction);
+            }
+
+            processOutputSlot(lastLineCache, s, connectionList, controlPointIndex + 1, p, newPredecessor, offx, offy, animator);
+        }
+    }
+
+    @Override
+    public Lookup getLookup() {
+        return lookup;
+    }
+
+    private void gotoFigures(final Collection<Figure> figures) {
+        Rectangle overall = null;
+        getModel().showFigures(figures);
+        for (Figure f : figures) {
+
+            FigureWidget fw = getWidget(f);
+            if (fw != null) {
+                Rectangle r = fw.getBounds();
+                Point p = fw.getLocation();
+                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);
+        }
+    }
+
+    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());
+        center.x -= getScrollPane().getViewport().getViewRect().width / 2;
+        center.y -= getScrollPane().getViewport().getViewRect().height / 2;
+
+        // Ensure to be within area
+        center.x = Math.max(0, center.x);
+        center.x = Math.min(getScrollPane().getViewport().getViewSize().width - getScrollPane().getViewport().getViewRect().width, center.x);
+        center.y = Math.max(0, center.y);
+        center.y = Math.min(getScrollPane().getViewport().getViewSize().height - getScrollPane().getViewport().getViewRect().height, center.y);
+
+        return center;
+    }
+
+    private void centerRectangle(Rectangle r) {
+
+        if (getScrollPane().getViewport().getViewRect().width == 0 || getScrollPane().getViewport().getViewRect().height == 0) {
+            return;
+        }
+
+        Rectangle r2 = new Rectangle(r.x, r.y, r.width, r.height);
+        r2 = convertSceneToView(r2);
+
+        double factorX = (double) r2.width / (double) getScrollPane().getViewport().getViewRect().width;
+        double factorY = (double) r2.height / (double) getScrollPane().getViewport().getViewRect().height;
+        double factor = Math.max(factorX, factorY);
+        if (factor >= 1.0) {
+            Point p = getScrollPane().getViewport().getViewPosition();
+            setZoomFactor(getZoomFactor() / factor);
+            r2.x /= factor;
+            r2.y /= factor;
+            r2.width /= factor;
+            r2.height /= factor;
+            getScrollPane().getViewport().setViewPosition(calcCenter(r2));
+        } else {
+            getScrollPane().getViewport().setViewPosition(calcCenter(r2));
+        }
+    }
+
+    void setSelection(Collection<Figure> list) {
+        super.setSelectedObjects(new HashSet<>(list));
+        centerFigures(list);
+    }
+
+    private boolean isVisible(Figure f) {
+        for (Integer n : f.getSource().getSourceNodesAsSet()) {
+            if (getModel().getHiddenNodes().contains(n)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static boolean doesIntersect(Set<?> s1, Set<?> s2) {
+        if (s1.size() > s2.size()) {
+            Set<?> tmp = s1;
+            s1 = s2;
+            s2 = tmp;
+        }
+
+        for (Object o : s1) {
+            if (s2.contains(o)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private void updateHiddenNodes(Set<Integer> newHiddenNodes, boolean doRelayout) {
+
+        System.out.println("newHiddenNodes: " + newHiddenNodes);
+
+        Diagram diagram = getModel().getDiagramToView();
+        assert diagram != null;
+
+        Set<Widget> oldVisibleWidgets = new HashSet<>();
+
+        for (Figure f : diagram.getFigures()) {
+            FigureWidget w = getWidget(f);
+            if (w != null && w.isVisible()) {
+                oldVisibleWidgets.add(w);
+            }
+        }
+
+        for (Figure f : diagram.getFigures()) {
+            boolean hiddenAfter = doesIntersect(f.getSource().getSourceNodesAsSet(), newHiddenNodes);
+
+            FigureWidget w = getWidget(f);
+            w.setBoundary(false);
+            if (!hiddenAfter) {
+                // Figure is shown
+                w.setVisible(true);
+            } else {
+                // Figure is hidden
+                w.setVisible(false);
+            }
+        }
+
+        if (getModel().getShowNodeHull()) {
+            List<FigureWidget> boundaries = new ArrayList<>();
+            for (Figure f : diagram.getFigures()) {
+                FigureWidget w = getWidget(f);
+                if (!w.isVisible()) {
+                    Set<Figure> set = new HashSet<>(f.getPredecessorSet());
+                    set.addAll(f.getSuccessorSet());
+
+                    boolean b = false;
+                    for (Figure neighbor : set) {
+                        FigureWidget neighborWidget = getWidget(neighbor);
+                        if (neighborWidget.isVisible()) {
+                            b = true;
+                            break;
+                        }
+                    }
+
+                    if (b) {
+                        w.setBoundary(true);
+                        boundaries.add(w);
+                    }
+                }
+            }
+
+            for (FigureWidget w : boundaries) {
+                if (w.isBoundary()) {
+                    w.setVisible(true);
+                }
+            }
+        }
+
+        if (doRelayout) {
+            relayout(oldVisibleWidgets);
+        }
+        this.validate();
+    }
+
+    private void showFigure(Figure f) {
+        HashSet<Integer> newHiddenNodes = new HashSet<>(getModel().getHiddenNodes());
+        newHiddenNodes.removeAll(f.getSource().getSourceNodesAsSet());
+        updateHiddenNodes(newHiddenNodes, true);
+    }
+
+    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 = getWidget(f);
+        if (fw != null) {
+            setSelection(new HashSet<>(Arrays.asList(f)));
+        }
+    }
+
+    public JPopupMenu createPopupMenu() {
+        JPopupMenu menu = new JPopupMenu();
+        for (Action a : actions) {
+            if (a == null) {
+                menu.addSeparator();
+            } else {
+                menu.add(a);
+            }
+        }
+        return menu;
+    }
+    
+    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);
+        }
+    };
+
+    @Override
+    public void showAll() {
+        // TODO(tw): Implement.
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/scene/GraphCompilationViewer.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.view.scene;
+
+import com.sun.hotspot.igv.svg.BatikSVG;
+import com.oracle.graal.visualizer.editor.CompilationViewer;
+import com.oracle.graal.visualizer.editor.DiagramViewModel;
+import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.view.actions.*;
+import java.awt.Component;
+import java.awt.Graphics2D;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.*;
+import java.util.Collection;
+import javax.swing.Action;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ProxyLookup;
+
+public class GraphCompilationViewer implements CompilationViewer, PropertyChangeListener {
+    
+    private DiagramScene scene;
+    private PredSuccAction predSuccAction;
+
+    GraphCompilationViewer(DiagramViewModel model) {
+        
+        scene = new DiagramScene(model);
+        
+        Action[] actions = new Action[]{
+        };
+        
+        scene.setActions(actions);
+    }
+
+    @Override
+    public Lookup getLookup() {
+        return scene.getLookup();
+    }
+
+    @Override
+    public Component getComponent() {
+        return scene.getComponent();
+    }
+
+    @Override
+    public void propertyChange(PropertyChangeEvent evt) {
+        if (evt.getSource() == this.predSuccAction) {
+            boolean b = (Boolean) predSuccAction.getValue(PredSuccAction.STATE);
+            scene.getModel().setShowNodeHull(b);
+        } else {
+            assert false : "Unknown event source";
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/scene/GraphCompilationViewerFactory.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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.scene;
+
+import com.oracle.graal.visualizer.editor.CompilationViewer;
+import com.oracle.graal.visualizer.editor.CompilationViewerFactory;
+import com.oracle.graal.visualizer.editor.DiagramViewModel;
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.filter.FilterChain;
+import com.sun.hotspot.igv.filter.FilterChainProvider;
+import org.openide.util.Lookup;
+
+public class GraphCompilationViewerFactory implements CompilationViewerFactory{
+
+    @Override
+    public CompilationViewer createViewer(InputGraph firstGraph, InputGraph secondGraph) {
+        FilterChain filterChain;
+        FilterChain sequence;
+        FilterChainProvider provider = Lookup.getDefault().lookup(FilterChainProvider.class);
+        if (provider == null) {
+            filterChain = new FilterChain();
+            sequence = new FilterChain();
+        } else {
+            filterChain = provider.getFilterChain();
+            sequence = provider.getSequence();
+        }
+        DiagramViewModel model = new DiagramViewModel(firstGraph, secondGraph, firstGraph.getGroup(), filterChain, filterChain);
+        return new GraphCompilationViewer(model);
+    }
+
+    @Override
+    public String getName() {
+        return "Graph";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.view.widgets;
+
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.util.DoubleClickAction;
+import com.sun.hotspot.igv.util.DoubleClickHandler;
+import com.sun.hotspot.igv.util.PropertiesSheet;
+import com.sun.hotspot.igv.view.scene.DiagramScene;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+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.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+import org.openide.nodes.Sheet;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class FigureWidget extends Widget implements Properties.Provider, PopupMenuProvider, DoubleClickHandler {
+
+    public static final boolean VERTICAL_LAYOUT = true;
+    //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;
+    private Widget middleWidget;
+    private ArrayList<LabelWidget> labelWidgets;
+    private DiagramScene diagramScene;
+    private boolean boundary;
+    private Node node;
+    private Widget dummyTop;
+
+    public void setBoundary(boolean b) {
+        boundary = b;
+    }
+
+    public boolean isBoundary() {
+        return boundary;
+    }
+
+    public Node getNode() {
+        return node;
+    }
+
+	@Override
+	public boolean isHitAt(Point localLocation) {
+		return middleWidget.isHitAt(localLocation);
+	}
+    
+
+    public FigureWidget(final Figure f, WidgetAction hoverAction, WidgetAction selectAction, DiagramScene scene, Widget parent) {
+
+        super(scene);
+
+        assert this.getScene() != null;
+        assert this.getScene().getView() != null;
+
+        this.figure = f;
+        font = f.getDiagram().getFont();
+        boldFont = f.getDiagram().getFont().deriveFont(Font.BOLD);
+        this.setCheckClipping(true);
+        this.diagramScene = scene;
+        parent.addChild(this);
+
+	Widget outer = new Widget(scene);
+	outer.setBackground(f.getColor());
+	outer.setLayout(LayoutFactory.createOverlayLayout());
+	
+        middleWidget = new Widget(scene);
+        middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout(LayoutFactory.SerialAlignment.CENTER, 0));
+        middleWidget.setBackground(f.getColor());
+        middleWidget.setOpaque(true);
+        //middleWidget.setBorder(BorderFactory.createLineBorder(Color.BLACK));
+        middleWidget.getActions().addAction(new DoubleClickAction(this));
+	middleWidget.setCheckClipping(true);
+
+        labelWidgets = new ArrayList<>();
+
+        String[] strings = figure.getLines();
+
+        dummyTop = new Widget(scene);
+        dummyTop.setMinimumSize(new Dimension(Figure.INSET / 2, 1));
+        middleWidget.addChild(dummyTop);
+
+
+        for (String cur : strings) {
+
+            String displayString = cur;
+
+            LabelWidget lw = new LabelWidget(scene);
+            labelWidgets.add(lw);
+            middleWidget.addChild(lw);
+            lw.setLabel(displayString);
+            lw.setFont(font);
+            lw.setForeground(Color.BLACK);
+            lw.setAlignment(LabelWidget.Alignment.CENTER);
+            lw.setVerticalAlignment(LabelWidget.VerticalAlignment.CENTER);
+	    lw.setBorder(BorderFactory.createEmptyBorder());
+        }
+
+        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()));
+	//outer.addChild(middleWidget);
+        this.addChild(middleWidget);
+
+        // Initialize node for property sheet
+        node = new AbstractNode(Children.LEAF) {
+
+            @Override
+            protected Sheet createSheet() {
+                Sheet s = super.createSheet();
+                PropertiesSheet.initializeSheet(f.getProperties(), s);
+                return s;
+            }
+        };
+        node.setDisplayName(getName());
+    }
+
+    public Widget getLeftWidget() {
+        return leftWidget;
+    }
+
+    public Widget getRightWidget() {
+        return rightWidget;
+    }
+
+    @Override
+    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
+        super.notifyStateChanged(previousState, state);
+
+        Color borderColor = Color.BLACK;
+	Color innerBorderColor = getFigure().getColor();
+        int thickness = 1;
+        boolean repaint = false;
+        Font f = font;
+        if (state.isSelected() || state.isHighlighted()) {
+            thickness = 2;
+	}
+	if(state.isSelected()) {
+            f = boldFont;
+		innerBorderColor = borderColor;
+        } else {
+	}
+
+        if (state.isHighlighted()) {
+		innerBorderColor = borderColor = Color.BLUE;
+		repaint = true;
+        } else {
+		repaint = true;
+	}
+
+        if (state.isHovered() != previousState.isHovered()) {
+
+		/*
+            if (state.isHovered()) {
+                diagramScene.addAllHighlighted(this.getFigure().getSource().getSourceNodesAsSet());
+            } else {
+                diagramScene.removeAllHighlighted(this.getFigure().getSource().getSourceNodesAsSet());
+            }*/
+            repaint = true;
+        }
+
+        if (state.isSelected() != previousState.isSelected()) {
+            repaint = true;
+        }
+
+        if (repaint) {
+            middleWidget.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(borderColor, 1), BorderFactory.createLineBorder(innerBorderColor, 1)));
+            for (LabelWidget labelWidget : labelWidgets) {
+                labelWidget.setFont(f);
+            }
+            repaint();
+        }
+    }
+
+    public String getName() {
+        return getProperties().get("name");
+    }
+
+    @Override
+    public Properties getProperties() {
+        return figure.getProperties();
+    }
+
+    public Figure getFigure() {
+        return figure;
+    }
+
+    @Override
+    protected void paintChildren() {
+        Composite oldComposite = null;
+        if (boundary) {
+            oldComposite = getScene().getGraphics().getComposite();
+            float alpha = DiagramScene.ALPHA;
+            this.getScene().getGraphics().setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
+        }
+
+        if (diagramScene.getZoomFactor() < LABEL_ZOOM_FACTOR) {
+
+            for (LabelWidget labelWidget : labelWidgets) {
+                labelWidget.setVisible(false);
+            }
+            super.paintChildren();
+            for (LabelWidget labelWidget : labelWidgets) {
+                labelWidget.setVisible(true);
+            }
+
+        } else {
+            super.paintChildren();
+        }
+
+        if (boundary) {
+            getScene().getGraphics().setComposite(oldComposite);
+        }
+    }
+ 
+    @Override
+    public JPopupMenu getPopupMenu(Widget widget, Point point) {
+        JPopupMenu menu = diagramScene.createPopupMenu();
+        menu.addSeparator();
+
+        JMenu predecessors = new JMenu("Nodes Above");
+        predecessors.addMenuListener(new NeighborMenuListener(predecessors, getFigure(), false));
+        menu.add(predecessors);
+
+        JMenu successors = new JMenu("Nodes Below");
+        successors.addMenuListener(new NeighborMenuListener(successors, getFigure(), true));
+        menu.add(successors);
+
+        return menu;
+    }
+
+    /**
+     * Builds the submenu for a figure's neighbors on demand.
+     */
+    private class NeighborMenuListener implements MenuListener {
+
+        private final JMenu menu;
+        private final Figure figure;
+        private final boolean successors;
+
+        public NeighborMenuListener(JMenu menu, Figure figure, boolean successors) {
+            this.menu = menu;
+            this.figure = figure;
+            this.successors = successors;
+        }
+
+        @Override
+        public void menuSelected(MenuEvent e) {
+            if (menu.getItemCount() > 0) {
+                // already built before
+                return;
+            }
+
+            Set<Figure> set = figure.getPredecessorSet();
+            if (successors) {
+                set = figure.getSuccessorSet();
+            }
+
+            boolean first = true;
+            for (Figure f : set) {
+                if (f == figure) {
+                    continue;
+                }
+
+                if (first) {
+                    first = false;
+                } else {
+                    menu.addSeparator();
+                }
+
+                Action go = diagramScene.createGotoAction(f);
+                menu.add(go);
+
+                JMenu preds = new JMenu("Nodes Above");
+                preds.addMenuListener(new NeighborMenuListener(preds, f, false));
+                menu.add(preds);
+
+                JMenu succs = new JMenu("Nodes Below");
+                succs.addMenuListener(new NeighborMenuListener(succs, f, true));
+                menu.add(succs);
+            }
+
+            if (menu.getItemCount() == 0) {
+                menu.add("(none)");
+            }
+        }
+
+        @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()) {
+            final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes());
+            hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet());
+            this.diagramScene.getModel().showNot(hiddenNodes);
+        } else if (isBoundary()) {
+
+            final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes());
+            hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet());
+            this.diagramScene.getModel().showNot(hiddenNodes);
+        } else {
+            final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes());
+            hiddenNodes.addAll(this.getFigure().getSource().getSourceNodesAsSet());
+            this.diagramScene.getModel().showNot(hiddenNodes);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/widgets/InputSlotWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,73 @@
+/*
+ * 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.Figure;
+import com.sun.hotspot.igv.graph.InputSlot;
+import com.sun.hotspot.igv.view.scene.DiagramScene;
+import java.awt.Point;
+import java.util.List;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InputSlotWidget extends SlotWidget {
+
+    private InputSlot inputSlot;
+
+    public InputSlotWidget(InputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
+        super(slot, scene, parent, fw);
+        inputSlot = slot;
+        //init();
+        //getFigureWidget().getLeftWidget().addChild(this);
+        Point p = inputSlot.getRelativePosition();
+        p.x -= this.calculateClientArea().width / 2;
+        p.y += Figure.SLOT_START;
+        this.setPreferredLocation(p);
+    }
+
+    public InputSlot getInputSlot() {
+        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);
+        }
+
+        double x = 0;
+        List<InputSlot> slots = inputSlot.getFigure().getInputSlots();
+        assert slots.contains(inputSlot);
+        return new Point((int) x, (int) (calculateRelativeY(slots.size(), slots.indexOf(inputSlot))));
+    }*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,343 @@
+/*
+ * 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.graph.InputSlot;
+import com.sun.hotspot.igv.graph.OutputSlot;
+import com.sun.hotspot.igv.view.scene.DiagramScene;
+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;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class LineWidget extends Widget implements PopupMenuProvider {
+
+    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;
+    public final int BOLD_STROKE_WIDTH = 2;
+    public final int HOVER_STROKE_WIDTH = 3;
+    private static double ZOOM_FACTOR = 0.1;
+    private OutputSlot outputSlot;
+    private DiagramScene scene;
+    private List<Connection> connections;
+    private Point from;
+    private Point to;
+    private Rectangle clientArea;
+    private Color color = Color.BLACK;
+    private LineWidget predecessor;
+    private List<LineWidget> successors;
+    private boolean highlighted;
+    private boolean popupVisible;
+    private boolean isBold;
+    private boolean isDashed;
+
+    public LineWidget(DiagramScene scene, OutputSlot s, List<Connection> connections, Point from, Point to, LineWidget predecessor, SceneAnimator animator, boolean isBold, boolean isDashed) {
+        super(scene);
+        this.scene = scene;
+        this.outputSlot = s;
+        this.connections = connections;
+        this.from = from;
+        this.to = to;
+        this.predecessor = predecessor;
+        this.successors = new ArrayList<>();
+        if (predecessor != null) {
+            predecessor.addSuccessor(this);
+        }
+
+        this.isBold = isBold;
+        this.isDashed = isDashed;
+
+        int minX = from.x;
+        int minY = from.y;
+        int maxX = to.x;
+        int maxY = to.y;
+        if (minX > maxX) {
+            int tmp = minX;
+            minX = maxX;
+            maxX = tmp;
+        }
+
+        if (minY > maxY) {
+            int tmp = minY;
+            minY = maxY;
+            maxY = tmp;
+        }
+
+        clientArea = new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1);
+        clientArea.grow(BORDER, BORDER);
+
+        if (connections.size() > 0) {
+            color = connections.get(0).getColor();
+        }
+
+        this.setToolTipText("<HTML>" + generateToolTipText(this.connections) + "</HTML>");
+
+        this.setCheckClipping(true);
+
+        this.getActions().addAction(ActionFactory.createPopupMenuAction(this));
+        if (animator == null) {
+            this.setBackground(color);
+        } else {
+            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() {
+        return from;
+    }
+
+    public Point getTo() {
+        return to;
+    }
+
+    private void addSuccessor(LineWidget widget) {
+        this.successors.add(widget);
+    }
+
+    @Override
+    protected Rectangle calculateClientArea() {
+        return clientArea;
+    }
+
+    @Override
+    protected void paintWidget() {
+        if (scene.getZoomFactor() < ZOOM_FACTOR) {
+            return;
+        }
+
+        Graphics2D g = getScene().getGraphics();
+        g.setPaint(this.getBackground());
+        float width = 1.0f;
+
+        if (isBold) {
+            width = BOLD_STROKE_WIDTH;
+        }
+
+        if (highlighted || popupVisible) {
+            width = HOVER_STROKE_WIDTH;
+        }
+
+        Stroke oldStroke = g.getStroke();
+        if (isDashed) {
+            float[] dashPattern = {5, 5, 5, 5};
+            g.setStroke(new BasicStroke(width, BasicStroke.CAP_BUTT,
+                    BasicStroke.JOIN_MITER, 10,
+                    dashPattern, 0));
+        } else {
+            g.setStroke(new BasicStroke(width));
+        }
+
+        g.drawLine(from.x, from.y, to.x, to.y);
+
+        boolean sameFrom = false;
+        boolean sameTo = successors.size() == 0;
+        for (LineWidget w : successors) {
+            if (w.getFrom().equals(getTo())) {
+                sameTo = true;
+            }
+        }
+
+        if (predecessor == null || predecessor.getTo().equals(getFrom())) {
+            sameFrom = true;
+        }
+
+
+        int size = ARROW_SIZE;
+        if (isBold) {
+            size = BOLD_ARROW_SIZE;
+        }
+        if (highlighted || popupVisible) {
+            size = HOVER_ARROW_SIZE;
+        }
+        if (!sameFrom) {
+            g.fillPolygon(
+                    new int[]{from.x - size / 2, from.x + size / 2, from.x},
+                    new int[]{from.y - size / 2, from.y - size / 2, from.y + size / 2},
+                    3);
+        }
+        if (!sameTo) {
+            g.fillPolygon(
+                    new int[]{to.x - size / 2, to.x + size / 2, to.x},
+                    new int[]{to.y - size / 2, to.y - size / 2, to.y + size / 2},
+                    3);
+        }
+        g.setStroke(oldStroke);
+    }
+
+    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);
+    }
+
+    private void setPopupVisible(boolean b) {
+        this.popupVisible = b;
+        this.revalidate(true);
+    }
+
+    @Override
+    public boolean isHitAt(Point localPoint) {
+        return Line2D.ptLineDistSq(from.x, from.y, to.x, to.y, localPoint.x, localPoint.y) <= BORDER * BORDER;
+    }
+
+    @Override
+    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
+        if (previousState.isHovered() != state.isHovered()) {
+            setRecursiveHighlighted(state.isHovered());
+        }
+    }
+
+    private void setRecursiveHighlighted(boolean b) {
+        LineWidget cur = predecessor;
+        while (cur != null) {
+            cur.setHighlighted(b);
+            cur = cur.predecessor;
+        }
+
+        highlightSuccessors(b);
+        this.setHighlighted(b);
+    }
+
+    private void highlightSuccessors(boolean b) {
+        for (LineWidget s : successors) {
+            s.setHighlighted(b);
+            s.highlightSuccessors(b);
+        }
+    }
+
+    private void setRecursivePopupVisible(boolean b) {
+        LineWidget cur = predecessor;
+        while (cur != null) {
+            cur.setPopupVisible(b);
+            cur = cur.predecessor;
+        }
+
+        popupVisibleSuccessors(b);
+        setPopupVisible(b);
+    }
+
+    private void popupVisibleSuccessors(boolean b) {
+        for (LineWidget s : successors) {
+            s.setPopupVisible(b);
+            s.popupVisibleSuccessors(b);
+        }
+    }
+
+    @Override
+    public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
+        JPopupMenu menu = new JPopupMenu();
+        menu.add(scene.createGotoAction(outputSlot.getFigure()));
+        menu.addSeparator();
+
+        for (Connection c : connections) {
+            InputSlot s = c.getInputSlot();
+            menu.add(scene.createGotoAction(s.getFigure()));
+        }
+
+        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) {
+            }
+        });
+
+        return menu;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/widgets/OutputSlotWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,76 @@
+/*
+ * 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.Figure;
+import com.sun.hotspot.igv.graph.OutputSlot;
+import com.sun.hotspot.igv.view.scene.DiagramScene;
+import java.awt.Point;
+import java.util.List;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class OutputSlotWidget extends SlotWidget {
+
+    private OutputSlot outputSlot;
+
+    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;
+        //p.x += this.calculateClientArea().width / 2;
+        this.setPreferredLocation(p);
+    }
+
+    public OutputSlot getOutputSlot() {
+        return outputSlot;
+    }
+
+    @Override
+    protected int calculateSlotWidth() {
+        
+        List<OutputSlot> slots = getSlot().getFigure().getOutputSlots();
+        assert slots.contains(getSlot());
+        return calculateWidth(slots.size());
+        
+    }
+    /*
+    protected Point calculateRelativeLocation() {
+        if (getFigureWidget().getBounds() == null) {
+            return new Point(0, 0);
+        }
+
+        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))));
+    }*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/View/src/com/sun/hotspot/igv/view/widgets/SlotWidget.java	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,177 @@
+/*
+ * 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.Figure;
+import com.sun.hotspot.igv.graph.OutputSlot;
+import com.sun.hotspot.igv.graph.Slot;
+import com.sun.hotspot.igv.util.DoubleClickHandler;
+import com.sun.hotspot.igv.view.scene.DiagramScene;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+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 implements DoubleClickHandler {
+
+    private Slot slot;
+    private FigureWidget figureWidget;
+    private static double TEXT_ZOOM_FACTOR = 0.9;
+    private static double ZOOM_FACTOR = 0.6;
+    private DiagramScene diagramScene;
+
+    public SlotWidget(Slot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
+        super(scene);
+        this.diagramScene = scene;
+        this.slot = slot;
+        figureWidget = fw;
+        this.setToolTipText("<HTML>" + slot.getToolTipText() + "</HTML>");
+        this.setCheckClipping(true);
+        parent.addChild(this);
+        
+        //this.setPreferredBounds(this.calculateClientArea());
+    }
+    
+    
+    @Override
+    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
+        super.notifyStateChanged(previousState, state);
+	repaint();
+    }
+    
+    public Slot getSlot() {
+        return slot;
+    }
+
+    public FigureWidget getFigureWidget() {
+        return figureWidget;
+    }
+
+    @Override
+    protected void paintWidget() {
+
+        if (getScene().getZoomFactor() < ZOOM_FACTOR) {
+            return;
+        }
+
+        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(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.getState().isHighlighted()) {
+                g.setColor(Color.BLUE);
+            } else {
+                g.setColor(Color.BLACK);
+            }
+            int r = 2;
+            if (slot instanceof OutputSlot) {
+                g.fillOval(w/2-r, Figure.SLOT_WIDTH - Figure.SLOT_START - r, 2*r, 2*r);
+                //g.fillArc(w / 2 - r, -r, 2*r, 2*r, 180, 180);
+            } else {
+                g.fillOval(w/2-r, Figure.SLOT_START - r, 2*r, 2*r);
+                //g.fillArc(w / 2 - r, h - r, 2*r, 2*r, 0, 180);
+            }
+        }
+    }
+
+    @Override
+    protected Rectangle calculateClientArea() {
+        return new Rectangle(0, 0, slot.getWidth(), Figure.SLOT_WIDTH);
+    }
+ 
+    protected abstract int calculateSlotWidth();
+    
+    protected int calculateWidth(int count) {
+        return getFigureWidget().getFigure().getWidth() / count;
+    }
+
+    @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());
+        } 
+
+        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/visualizer/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,7 @@
+currentVersion=Graal Visualizer {0}
+LBL_splash_window_title=Starting Graal Visualizer
+SPLASH_WIDTH=475
+SplashProgressBarBounds=0,273,475,6
+SplashProgressBarColor=0xFFFFFF
+SplashRunningTextBounds=10,283,460,12
+SplashRunningTextColor=0xFFFFFF
Binary file visualizer/branding/core/core.jar/org/netbeans/core/startup/frame.gif has changed
Binary file visualizer/branding/core/core.jar/org/netbeans/core/startup/frame32.gif has changed
Binary file visualizer/branding/core/core.jar/org/netbeans/core/startup/frame48.gif has changed
Binary file visualizer/branding/core/core.jar/org/netbeans/core/startup/splash.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,2 @@
+CTL_MainWindow_Title=Graal Visualizer {0}
+CTL_MainWindow_Title_No_Project=Graal Visualizer {0}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/build.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,16 @@
+<?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="Graal Visualizer" 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/visualizer/nbproject/build-impl.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         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">
+        <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-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="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>
+                <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>
+    <import file="${harness.dir}/suite.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/nbproject/genfiles.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,11 @@
+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=3c2c6126
+nbproject/build-impl.xml.script.CRC32=b26e57e5
+nbproject/build-impl.xml.stylesheet.CRC32=0f381476@2.47.1
+nbproject/platform.xml.data.CRC32=3c2c6126
+nbproject/platform.xml.script.CRC32=db9e1f43
+nbproject/platform.xml.stylesheet.CRC32=df8ac4dd@2.47.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/nbproject/platform.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,212 @@
+nbplatform.active=default
+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.1.1/uc/final/distribution/catalog.xml.gz
+suite.dir=${basedir}
+nbplatform.active.dir=${suite.dir}/nbplatform
+nbplatform.default.netbeans.dest.dir=${suite.dir}/nbplatform
+nbplatform.default.harness.dir=${nbplatform.default.netbeans.dest.dir}/harness
+harness.dir=${nbplatform.active.dir}/harness
+cluster.path=\
+    ${nbplatform.active.dir}/ide:\
+    ${nbplatform.active.dir}/platform
+disabled.modules=\
+    com.jcraft.jsch,\
+    com.jcraft.jzlib,\
+    org.apache.commons.codec,\
+    org.apache.commons.httpclient,\
+    org.apache.commons.io,\
+    org.apache.commons.lang,\
+    org.apache.commons.logging,\
+    org.apache.ws.commons.util,\
+    org.apache.xml.resolver,\
+    org.apache.xmlrpc,\
+    org.eclipse.core.contenttype,\
+    org.eclipse.core.jobs,\
+    org.eclipse.core.net,\
+    org.eclipse.core.runtime,\
+    org.eclipse.core.runtime.compatibility.auth,\
+    org.eclipse.equinox.app,\
+    org.eclipse.equinox.common,\
+    org.eclipse.equinox.preferences,\
+    org.eclipse.equinox.registry,\
+    org.eclipse.equinox.security,\
+    org.eclipse.jgit,\
+    org.eclipse.mylyn.bugzilla.core,\
+    org.eclipse.mylyn.commons.core,\
+    org.eclipse.mylyn.commons.net,\
+    org.eclipse.mylyn.commons.xmlrpc,\
+    org.eclipse.mylyn.tasks.core,\
+    org.mozilla.rhino.patched,\
+    org.netbeans.api.debugger,\
+    org.netbeans.api.java.classpath,\
+    org.netbeans.api.xml,\
+    org.netbeans.core.browser,\
+    org.netbeans.core.execution,\
+    org.netbeans.core.ide,\
+    org.netbeans.core.io.ui,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.nativeaccess,\
+    org.netbeans.core.osgi,\
+    org.netbeans.lib.cvsclient,\
+    org.netbeans.lib.terminalemulator,\
+    org.netbeans.libs.antlr3.runtime,\
+    org.netbeans.libs.bytelist,\
+    org.netbeans.libs.commons_net,\
+    org.netbeans.libs.freemarker,\
+    org.netbeans.libs.git,\
+    org.netbeans.libs.ini4j,\
+    org.netbeans.libs.jaxb,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.junit4,\
+    org.netbeans.libs.jvyamlb,\
+    org.netbeans.libs.lucene,\
+    org.netbeans.libs.smack,\
+    org.netbeans.libs.svnClientAdapter,\
+    org.netbeans.libs.svnClientAdapter.javahl,\
+    org.netbeans.libs.svnClientAdapter.svnkit,\
+    org.netbeans.libs.swingx,\
+    org.netbeans.libs.xerces,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.bugtracking,\
+    org.netbeans.modules.bugtracking.bridge,\
+    org.netbeans.modules.bugzilla,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.csl.api,\
+    org.netbeans.modules.css.editor,\
+    org.netbeans.modules.css.lib,\
+    org.netbeans.modules.css.visual,\
+    org.netbeans.modules.db,\
+    org.netbeans.modules.db.core,\
+    org.netbeans.modules.db.dataview,\
+    org.netbeans.modules.db.drivers,\
+    org.netbeans.modules.db.kit,\
+    org.netbeans.modules.db.metadata.model,\
+    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.derby,\
+    org.netbeans.modules.dlight.nativeexecution,\
+    org.netbeans.modules.dlight.terminal,\
+    org.netbeans.modules.editor.bookmarks,\
+    org.netbeans.modules.editor.bracesmatching,\
+    org.netbeans.modules.editor.codetemplates,\
+    org.netbeans.modules.editor.completion,\
+    org.netbeans.modules.editor.guards,\
+    org.netbeans.modules.editor.indent.project,\
+    org.netbeans.modules.editor.kit,\
+    org.netbeans.modules.editor.macros,\
+    org.netbeans.modules.editor.structure,\
+    org.netbeans.modules.extbrowser,\
+    org.netbeans.modules.extexecution,\
+    org.netbeans.modules.extexecution.destroy,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.git,\
+    org.netbeans.modules.glassfish.common,\
+    org.netbeans.modules.gototest,\
+    org.netbeans.modules.gsf.codecoverage,\
+    org.netbeans.modules.gsf.testrunner,\
+    org.netbeans.modules.html,\
+    org.netbeans.modules.html.editor,\
+    org.netbeans.modules.html.editor.lib,\
+    org.netbeans.modules.html.lexer,\
+    org.netbeans.modules.html.parser,\
+    org.netbeans.modules.html.validation,\
+    org.netbeans.modules.httpserver,\
+    org.netbeans.modules.hudson,\
+    org.netbeans.modules.hudson.git,\
+    org.netbeans.modules.hudson.mercurial,\
+    org.netbeans.modules.hudson.subversion,\
+    org.netbeans.modules.hudson.tasklist,\
+    org.netbeans.modules.ide.kit,\
+    org.netbeans.modules.image,\
+    org.netbeans.modules.javascript.editing,\
+    org.netbeans.modules.javascript.hints,\
+    org.netbeans.modules.javascript.kit,\
+    org.netbeans.modules.javascript.refactoring,\
+    org.netbeans.modules.jellytools.ide,\
+    org.netbeans.modules.jumpto,\
+    org.netbeans.modules.keyring.impl,\
+    org.netbeans.modules.languages,\
+    org.netbeans.modules.languages.diff,\
+    org.netbeans.modules.languages.manifest,\
+    org.netbeans.modules.languages.yaml,\
+    org.netbeans.modules.lexer.nbbridge,\
+    org.netbeans.modules.localhistory,\
+    org.netbeans.modules.mercurial,\
+    org.netbeans.modules.netbinox,\
+    org.netbeans.modules.parsing.api,\
+    org.netbeans.modules.parsing.lucene,\
+    org.netbeans.modules.print.editor,\
+    org.netbeans.modules.project.ant,\
+    org.netbeans.modules.project.libraries,\
+    org.netbeans.modules.projectui,\
+    org.netbeans.modules.projectui.buildmenu,\
+    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.server,\
+    org.netbeans.modules.servletapi,\
+    org.netbeans.modules.spellchecker,\
+    org.netbeans.modules.spellchecker.apimodule,\
+    org.netbeans.modules.spellchecker.bindings.htmlxml,\
+    org.netbeans.modules.spellchecker.bindings.properties,\
+    org.netbeans.modules.spellchecker.dictionary_en,\
+    org.netbeans.modules.spellchecker.kit,\
+    org.netbeans.modules.spi.actions,\
+    org.netbeans.modules.subversion,\
+    org.netbeans.modules.swing.validation,\
+    org.netbeans.modules.target.iterator,\
+    org.netbeans.modules.tasklist.kit,\
+    org.netbeans.modules.tasklist.projectint,\
+    org.netbeans.modules.tasklist.todo,\
+    org.netbeans.modules.tasklist.ui,\
+    org.netbeans.modules.terminal,\
+    org.netbeans.modules.usersguide,\
+    org.netbeans.modules.utilities,\
+    org.netbeans.modules.utilities.project,\
+    org.netbeans.modules.versioning,\
+    org.netbeans.modules.versioning.indexingbridge,\
+    org.netbeans.modules.versioning.system.cvss.installer,\
+    org.netbeans.modules.versioning.util,\
+    org.netbeans.modules.web.client.tools.api,\
+    org.netbeans.modules.web.common,\
+    org.netbeans.modules.web.indent,\
+    org.netbeans.modules.xml,\
+    org.netbeans.modules.xml.axi,\
+    org.netbeans.modules.xml.catalog,\
+    org.netbeans.modules.xml.core,\
+    org.netbeans.modules.xml.jaxb.api,\
+    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.execution,\
+    org.openide.options,\
+    org.openide.util.enumerations
+## 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/visualizer/nbproject/platform.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -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>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/nbproject/project.properties	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,48 @@
+app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif
+app.name=idealgraphvisualizer
+app.title=IdealGraphVisualizer
+branding.token=${app.name}
+modules=\
+    ${project.com.sun.hotspot.igv.graph}:\
+    ${project.com.sun.hotspot.igv.filter}:\
+    ${project.com.sun.hotspot.igv.hierarchicallayout}:\
+    ${project.com.sun.hotspot.igv.layout}:\
+    ${project.com.sun.hotspot.igv.data}:\
+    ${project.com.sun.hotspot.igv.view}:\
+    ${project.com.sun.hotspot.igv.bytecodes}:\
+    ${project.com.sun.hotspot.igv.difference}:\
+    ${project.com.sun.hotspot.igv.settings}:\
+    ${project.com.sun.hotspot.igv.util}:\
+    ${project.com.sun.hotspot.igv.svg}:\
+    ${project.com.sun.hotspot.igv.filterwindow}:\
+    ${project.com.sun.hotspot.igv.graal}:\
+    ${project.at.ssw.visualizer.cfg}:\
+    ${project.org.eclipse.draw2d}:\
+    ${project.com.oracle.graal.visualizer.editor}:\
+    ${project.com.oracle.graal.visualizer.outline}:\
+    ${project.com.oracle.graal.visualizer.snapshots}:\
+    ${project.com.oracle.graal.visualizer.sharedactions}
+project.at.ssw.visualizer.cfg=ControlFlowEditor
+project.com.oracle.graal.visualizer.editor=Editor
+project.com.oracle.graal.visualizer.outline=OutlineView
+project.com.oracle.graal.visualizer.sharedactions=SharedActions
+project.com.oracle.graal.visualizer.snapshots=SnapshotsView
+project.com.sun.hotspot.igv.bytecodes=Bytecodes
+project.com.sun.hotspot.igv.data=Data
+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.settings=Settings
+project.com.sun.hotspot.igv.svg=BatikSVGProxy
+project.com.sun.hotspot.igv.view=View
+project.com.sun.hotspot.igv.util=Util
+
+project.org.eclipse.draw2d=Draw2DLibrary
+# Disable assertions for RequestProcessor to prevent annoying messages in case
+# of multiple SceneAnimator update tasks in the default RequestProcessor.
+run.args.extra = -J-client -J-da:org.openide.util.RequestProcessor
+debug.args.extra = -J-client -J-da:org.openide.util.RequestProcessor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/nbproject/project.xml	Wed Feb 08 21:15:00 2012 -0800
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project.suite</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-suite-project/1">
+            <name>Graal Visualizer</name>
+        </data>
+    </configuration>
+</project>