changeset 5754:d5ce56698bb3

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 03 Jul 2012 11:16:56 +0200
parents f9c9c01969c0 (current diff) a8c6104ef526 (diff)
children 12e5956a8fdd
files graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRDebugInfo.java graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/ExtendedRiRuntime.java graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/RiGraphCache.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LookupSwitchNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/TableSwitchNode.java graal/com.oracle.max.cri/src/com/oracle/max/cri/util/MemoryBarriers.java graal/com.oracle.max.cri/src/com/oracle/max/cri/util/UnsignedMath.java graal/com.oracle.max.criutils/src/com/oracle/max/criutils/BaseProfilingInfo.java graal/com.oracle.max.criutils/src/com/oracle/max/criutils/BaseUnresolvedField.java graal/com.oracle.max.criutils/src/com/oracle/max/criutils/BaseUnresolvedMethod.java graal/com.oracle.max.criutils/src/com/oracle/max/criutils/CompilationPrinter.java graal/com.oracle.max.criutils/src/com/oracle/max/criutils/JniMangle.java graal/com.oracle.max.criutils/src/com/oracle/max/criutils/SnapshotProfilingInfo.java graal/com.oracle.max.criutils/src/com/oracle/max/criutils/TypeCheckHints.java
diffstat 272 files changed, 8771 insertions(+), 3950 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.alloc/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.alloc</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/AssignRegisters.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/AssignRegisters.java	Tue Jul 03 11:16:56 2012 +0200
@@ -49,6 +49,7 @@
         ValueProcedure useProc =          new ValueProcedure() { @Override public Value doValue(Value value) { return use(value); } };
         ValueProcedure defProc =          new ValueProcedure() { @Override public Value doValue(Value value) { return def(value); } };
         ValueProcedure setReferenceProc = new ValueProcedure() { @Override public Value doValue(Value value) { return setReference(value); } };
+        StateProcedure finishProc =       new StateProcedure() { @Override public void doState(LIRFrameState state) { state.finish((BitSet) (curRegisterRefMap.clone()), (BitSet) (curFrameRefMap.clone()), frameMap); } };
 
         Debug.log("==== start assign registers ====");
         for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) {
@@ -70,17 +71,8 @@
                 op.forEachState(useProc);
                 op.forEachAlive(useProc);
 
-                if (op.info != null) {
-                    Debug.log("    registerRefMap: %s  frameRefMap: %s", curRegisterRefMap, curFrameRefMap);
-                    op.info.finish((BitSet) (curRegisterRefMap.clone()), (BitSet) (curFrameRefMap.clone()), frameMap);
-
-                    if (op instanceof LIRXirInstruction) {
-                        LIRXirInstruction xir = (LIRXirInstruction) op;
-                        if (xir.infoAfter != null) {
-                            xir.infoAfter.finish((BitSet) (curRegisterRefMap.clone()), (BitSet) (curFrameRefMap.clone()), frameMap);
-                        }
-                    }
-                }
+                // Build the reference map for the GC.
+                op.forEachState(finishProc);
 
                 // 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.
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/DataFlowAnalysis.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/DataFlowAnalysis.java	Tue Jul 03 11:16:56 2012 +0200
@@ -112,7 +112,7 @@
     }
 
     /**
-     * Numbers all instructions in all blocks. The numbering follows the {@linkplain ComputeLinearScanOrder linear scan order}.
+     * Numbers all instructions in all blocks. The numbering follows the linear scan order.
      */
     private void numberInstructions() {
         ValueProcedure defProc = new ValueProcedure() { @Override public Value doValue(Value value) { return setDef(value); } };
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/LinearScanAllocator.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/LinearScanAllocator.java	Tue Jul 03 11:16:56 2012 +0200
@@ -341,20 +341,20 @@
     }
 
     private Value use(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Input || mode == OperandMode.Alive;
+        assert mode == OperandMode.USE || 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)) {
+            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) {
+                if (mode == OperandMode.USE || curOutRegisterState[regNum] == curLoc) {
                     Debug.log("    use %s %s: use current register %s", mode, value, curLoc.location);
                     return curLoc;
                 }
@@ -373,10 +373,10 @@
         return value;
     }
 
-    private static final EnumSet<OperandFlag> SPILL_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+    private static final EnumSet<OperandFlag> SPILL_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK);
 
     private Value def(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Temp || mode == OperandMode.Output;
+        assert mode == OperandMode.TEMP || mode == OperandMode.DEF;
         if (isVariable(value)) {
             Debug.log("    def %s %s", mode, value);
             assert curLocations.get(asVariable(value)) == null;
@@ -396,7 +396,7 @@
             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);
+                Location newLoc = allocateRegister(oldLoc.variable, OperandMode.ALIVE, SPILL_FLAGS);
                 assert oldLoc != newLoc;
                 moveResolver.add(oldLoc, newLoc);
             }
@@ -417,7 +417,7 @@
                 Value phiInput = phiInputs[i];
 
                 if (isVariable(phiDefinition)) {
-                    Location hintResult = processRegisterHint(asVariable(phiDefinition), OperandMode.Output, phiInput);
+                    Location hintResult = processRegisterHint(asVariable(phiDefinition), OperandMode.DEF, phiInput);
                     if (hintResult != null) {
                         phiDefinitions[i] = hintResult;
                     }
@@ -444,7 +444,7 @@
     }
 
     private Location allocateRegister(final Variable variable, final OperandMode mode, EnumSet<OperandFlag> flags) {
-        if (flags.contains(OperandFlag.RegisterHint)) {
+        if (flags.contains(OperandFlag.HINT)) {
             Value hintResult = curOp.forEachRegisterHint(variable, mode, new ValueProcedure() {
                 @Override
                 public Value doValue(Value registerHint) {
@@ -476,7 +476,7 @@
             }
         }
 
-        if (flags.contains(OperandFlag.Stack) && betterSpillCandidate(curLocations.get(variable), bestSpillCandidate)) {
+        if (flags.contains(OperandFlag.STACK) && betterSpillCandidate(curLocations.get(variable), bestSpillCandidate)) {
             return selectSpillSlot(variable);
         }
 
@@ -509,11 +509,11 @@
 
     private boolean isFree(Register 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();
+            case USE: return curInRegisterState[reg.number] == null;
+            case ALIVE: return curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null;
+            case TEMP: return curOutRegisterState[reg.number] == null;
+            case DEF: return curOutRegisterState[reg.number] == null;
+            default: throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -552,7 +552,7 @@
         assert isFree(reg, mode);
 
         Location loc = new Location(variable, reg.asValue(variable.kind));
-        if (mode == OperandMode.Input || mode == OperandMode.Alive) {
+        if (mode == OperandMode.USE || mode == OperandMode.ALIVE) {
             curInRegisterState[reg.number] = loc;
         }
         curOutRegisterState[reg.number] = loc;
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/SpillAllAllocator.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/SpillAllAllocator.java	Tue Jul 03 11:16:56 2012 +0200
@@ -290,8 +290,8 @@
     }
 
     private Value load(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Input || mode == OperandMode.Alive;
-        if (flags.contains(OperandFlag.Stack)) {
+        assert mode == OperandMode.USE || mode == OperandMode.ALIVE;
+        if (flags.contains(OperandFlag.STACK)) {
             return useSlot(value);
         }
         if (isVariable(value)) {
@@ -301,7 +301,7 @@
                 // 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);
+                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);
@@ -314,15 +314,15 @@
     }
 
     private Value spill(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Temp || mode == OperandMode.Output;
-        if (flags.contains(OperandFlag.Stack)) {
+        assert mode == OperandMode.TEMP || mode == OperandMode.DEF;
+        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) {
+            if (mode == OperandMode.DEF) {
                 Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind));
                 curStackLocations.put(stackLoc);
                 moveResolver.add(regLoc, stackLoc);
@@ -360,7 +360,7 @@
     }
 
     private Location allocateRegister(final Variable variable, final Object[] inRegisterState, final Object[] outRegisterState, OperandMode mode, EnumSet<OperandFlag> flags) {
-        if (flags.contains(OperandFlag.RegisterHint)) {
+        if (flags.contains(OperandFlag.HINT)) {
             Value result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() {
                 @Override
                 public Value doValue(Value registerHint) {
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/IntervalPrinter.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/IntervalPrinter.java	Tue Jul 03 11:16:56 2012 +0200
@@ -167,7 +167,7 @@
                 if (op.hasCall()) {
                     intervals.get("call").ranges.add(new Range(curOpId, curOpId + 1));
                 }
-                if (op.info != null) {
+                if (op.hasState()) {
                     intervals.get("st").ranges.add(new Range(curOpId, curOpId + 1));
                 }
             }
@@ -228,7 +228,7 @@
     private String useKind(EnumSet<OperandFlag> flags) {
         if (curUseKind != null) {
             return curUseKind;
-        } else if (flags.contains(OperandFlag.Stack)) {
+        } else if (flags.contains(OperandFlag.STACK)) {
             return "S";
         } else {
             return "M";
@@ -242,7 +242,7 @@
                 interval.uses.add(new UsePosition(curOpId, useKind(flags)));
             }
             if (interval.lastTo == 0) {
-                interval.lastTo = curOpId + (mode == OperandMode.Alive ? 1 : 0);
+                interval.lastTo = curOpId + (mode == OperandMode.ALIVE ? 1 : 0);
             }
         }
         return value;
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/RegisterVerifier.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/RegisterVerifier.java	Tue Jul 03 11:16:56 2012 +0200
@@ -189,7 +189,7 @@
     private Value use(Value value, EnumSet<OperandFlag> flags) {
         if (!isConstant(value) && value != Value.IllegalValue && !isIgnoredRegister(value)) {
             Value actual = curInputState.get(key(value));
-            if (actual == null && flags.contains(OperandFlag.Uninitialized)) {
+            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));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.api.code</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Tue Jul 03 11:16:56 2012 +0200
@@ -74,7 +74,7 @@
     public final ByteOrder byteOrder;
 
     /**
-     * Mask of the barrier constants defined in {@link MemoryBarriers} denoting the barriers that
+     * Mask of the barrier constants denoting the barriers that
      * are not required to be explicitly inserted under this architecture.
      */
     public final int implicitMemoryBarriers;
@@ -82,7 +82,7 @@
     /**
      * Determines the barriers in a given barrier mask that are explicitly required on this architecture.
      *
-     * @param barriers a mask of the barrier constants defined in {@link MemoryBarriers}
+     * @param barriers a mask of the barrier constants
      * @return the value of {@code barriers} minus the barriers unnecessary on this architecture
      */
     public final int requiredBarriers(int barriers) {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Tue Jul 03 11:16:56 2012 +0200
@@ -29,8 +29,6 @@
 
 /**
  * Class for recording optimistic assumptions made during compilation.
- * Recorded assumption can be visited for subsequent processing using
- * an implementation of the {@link CiAssumptionProcessor} interface.
  */
 public final class Assumptions implements Serializable, Iterable<Assumptions.Assumption> {
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BailoutException.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BailoutException.java	Tue Jul 03 11:16:56 2012 +0200
@@ -43,7 +43,6 @@
 
     /**
      * Create a new {@code CiBailout}.
-     * @param reason a message indicating the reason with a String.format - syntax
      * @param args parameters to the formatter
      */
     public BailoutException(String format, Object... args) {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java	Tue Jul 03 11:16:56 2012 +0200
@@ -40,7 +40,7 @@
     public final int size;
 
     /**
-     * The size (in bytes) of an {@linkplain #registerAtIndex(int) indexable} slot in the CSA.
+     * The size (in bytes) of an {@linkplain #registerAt(int) indexable} slot in the CSA.
      */
     public final int slotSize;
 
@@ -52,7 +52,7 @@
     private final Register[] indexToReg;
 
     /**
-     * The list of registers {@linkplain #contains(Register) contained} by this CSA.
+     * The list of registers {@linkplain #contains(int) contained} by this CSA.
      */
     public final Register[] registers;
 
@@ -66,7 +66,7 @@
      * Creates a CSA layout.
      *
      * @param size size (in bytes) of the CSA. If this is {@code -1}, then the CSA size will be computed from {@code registers}.
-     * @param slotSize the size (in bytes) of an {@linkplain #registerAtIndex(int) indexable} slot in the CSA
+     * @param slotSize the size (in bytes) of an {@linkplain #registerAt(int) indexable} slot in the CSA
      * @param registers the registers that can be saved in the CSA
      */
     public CalleeSaveLayout(int frameOffsetToCSA, int size, int slotSize, Register... registers) {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java	Tue Jul 03 11:16:56 2012 +0200
@@ -33,8 +33,7 @@
 public class CallingConvention {
 
     /**
-     * Constants denoting the type of a call for which a calling convention is
-     * {@linkplain RegisterConfig#getCallingConvention(Type, CiKind[], CiTarget, boolean) requested}.
+     * Constants denoting the type of a call for which a calling convention is requested.
      */
     public enum Type {
         /**
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,42 +22,17 @@
  */
 package com.oracle.graal.api.code;
 
-import static java.lang.reflect.Modifier.*;
-
-import java.lang.annotation.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaTypeProfile.*;
 
 /**
- * Miscellaneous collection of utility methods used in the {@code CRI} project.
+ * Miscellaneous collection of utility methods used by {@code com.oracle.graal.api.code} and its clients.
  */
 public class CodeUtil {
 
     public static final String NEW_LINE = String.format("%n");
 
-    /**
-     * Gets the annotation of a particular type for a formal parameter of a given method.
-     *
-     * @param annotationClass the Class object corresponding to the annotation type
-     * @param parameterIndex the index of a formal parameter of {@code method}
-     * @param method the method for which a parameter annotation is being requested
-     * @return the annotation of type {@code annotationClass} for the formal parameter present, else null
-     * @throws IndexOutOfBoundsException if {@code parameterIndex} does not denote a formal parameter
-     */
-    public static <T extends Annotation> T getParameterAnnotation(Class<T> annotationClass, int parameterIndex, ResolvedJavaMethod method) {
-        if (parameterIndex >= 0) {
-            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
-            for (Annotation a : parameterAnnotations[parameterIndex]) {
-                if (a.annotationType() == annotationClass) {
-                    return annotationClass.cast(a);
-                }
-            }
-        }
-        return null;
-    }
-
     public static final int K = 1024;
     public static final int M = 1024 * 1024;
 
@@ -113,201 +88,6 @@
     }
 
     /**
-     * Gets a string for a given method formatted according to a given format specification. A format specification is
-     * composed of characters that are to be copied verbatim to the result and specifiers that denote an attribute of
-     * the method that is to be copied to the result. A specifier is a single character preceded by a '%' character. The
-     * accepted specifiers and the method attributes they denote are described below:
-     *
-     * <pre>
-     *     Specifier | Description                                          | Example(s)
-     *     ----------+------------------------------------------------------------------------------------------
-     *     'R'       | Qualified return type                                | "int" "java.lang.String"
-     *     'r'       | Unqualified return type                              | "int" "String"
-     *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
-     *     'h'       | Unqualified holder                                   | "Entry"
-     *     'n'       | Method name                                          | "add"
-     *     'P'       | Qualified parameter types, separated by ', '         | "int, java.lang.String"
-     *     'p'       | Unqualified parameter types, separated by ', '       | "int, String"
-     *     'f'       | Indicator if method is unresolved, static or virtual | "unresolved" "static" "virtual"
-     *     '%'       | A '%' character                                      | "%"
-     * </pre>
-     *
-     * @param format a format specification
-     * @param method the method to be formatted
-     * @param kinds if {@code true} then the types in {@code method}'s signature are printed in the
-     *            {@linkplain Kind#jniName JNI} form of their {@linkplain Kind kind}
-     * @return the result of formatting this method according to {@code format}
-     * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
-     */
-    public static String format(String format, JavaMethod method) throws IllegalFormatException {
-        final StringBuilder sb = new StringBuilder();
-        int index = 0;
-        Signature sig = null;
-        while (index < format.length()) {
-            final char ch = format.charAt(index++);
-            if (ch == '%') {
-                if (index >= format.length()) {
-                    throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a method format specification");
-                }
-                final char specifier = format.charAt(index++);
-                boolean qualified = false;
-                switch (specifier) {
-                    case 'R':
-                        qualified = true;
-                        // fall through
-                    case 'r': {
-                        if (sig == null) {
-                            sig = method.signature();
-                        }
-                        sb.append(MetaUtil.toJavaName(sig.returnType(null), qualified));
-                        break;
-                    }
-                    case 'H':
-                        qualified = true;
-                        // fall through
-                    case 'h': {
-                        sb.append(MetaUtil.toJavaName(method.holder(), qualified));
-                        break;
-                    }
-                    case 'n': {
-                        sb.append(method.name());
-                        break;
-                    }
-                    case 'P':
-                        qualified = true;
-                        // fall through
-                    case 'p': {
-                        if (sig == null) {
-                            sig = method.signature();
-                        }
-                        for (int i = 0; i < sig.argumentCount(false); i++) {
-                            if (i != 0) {
-                                sb.append(", ");
-                            }
-                            sb.append(MetaUtil.toJavaName(sig.argumentTypeAt(i, null), qualified));
-                        }
-                        break;
-                    }
-                    case 'f': {
-                        sb.append(!(method instanceof ResolvedJavaMethod) ? "unresolved" : isStatic(((ResolvedJavaMethod) method).accessFlags()) ? "static" : "virtual");
-                        break;
-                    }
-                    case '%': {
-                        sb.append('%');
-                        break;
-                    }
-                    default: {
-                        throw new UnknownFormatConversionException(String.valueOf(specifier));
-                    }
-                }
-            } else {
-                sb.append(ch);
-            }
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Gets a string for a given field formatted according to a given format specification. A format specification is
-     * composed of characters that are to be copied verbatim to the result and specifiers that denote an attribute of
-     * the field that is to be copied to the result. A specifier is a single character preceded by a '%' character. The
-     * accepted specifiers and the field attributes they denote are described below:
-     *
-     * <pre>
-     *     Specifier | Description                                          | Example(s)
-     *     ----------+------------------------------------------------------------------------------------------
-     *     'T'       | Qualified type                                       | "int" "java.lang.String"
-     *     't'       | Unqualified type                                     | "int" "String"
-     *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
-     *     'h'       | Unqualified holder                                   | "Entry"
-     *     'n'       | Field name                                           | "age"
-     *     'f'       | Indicator if field is unresolved, static or instance | "unresolved" "static" "instance"
-     *     '%'       | A '%' character                                      | "%"
-     * </pre>
-     *
-     * @param format a format specification
-     * @param field the field to be formatted
-     * @param kinds if {@code true} then {@code field}'s type is printed in the {@linkplain Kind#jniName JNI} form of
-     *            its {@linkplain Kind kind}
-     * @return the result of formatting this field according to {@code format}
-     * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
-     */
-    public static String format(String format, JavaField field) throws IllegalFormatException {
-        final StringBuilder sb = new StringBuilder();
-        int index = 0;
-        JavaType type = field.type();
-        while (index < format.length()) {
-            final char ch = format.charAt(index++);
-            if (ch == '%') {
-                if (index >= format.length()) {
-                    throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a field format specification");
-                }
-                final char specifier = format.charAt(index++);
-                boolean qualified = false;
-                switch (specifier) {
-                    case 'T':
-                        qualified = true;
-                        // fall through
-                    case 't': {
-                        sb.append(MetaUtil.toJavaName(type, qualified));
-                        break;
-                    }
-                    case 'H':
-                        qualified = true;
-                        // fall through
-                    case 'h': {
-                        sb.append(MetaUtil.toJavaName(field.holder(), qualified));
-                        break;
-                    }
-                    case 'n': {
-                        sb.append(field.name());
-                        break;
-                    }
-                    case 'f': {
-                        sb.append(!(field instanceof ResolvedJavaField) ? "unresolved" : isStatic(((ResolvedJavaField) field).accessFlags()) ? "static" : "instance");
-                        break;
-                    }
-                    case '%': {
-                        sb.append('%');
-                        break;
-                    }
-                    default: {
-                        throw new UnknownFormatConversionException(String.valueOf(specifier));
-                    }
-                }
-            } else {
-                sb.append(ch);
-            }
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Converts a Java source-language class name into the internal form.
-     *
-     * @param className the class name
-     * @return the internal name form of the class name
-     */
-    public static String toInternalName(String className) {
-        return "L" + className.replace('.', '/') + ";";
-    }
-
-    /**
-     * Prepends the String {@code indentation} to every line in String {@code lines}, including a possibly non-empty
-     * line following the final newline.
-     */
-    public static String indent(String lines, String indentation) {
-        if (lines.length() == 0) {
-            return lines;
-        }
-        final String newLine = "\n";
-        if (lines.endsWith(newLine)) {
-            return indentation + (lines.substring(0, lines.length() - 1)).replace(newLine, newLine + indentation) + newLine;
-        }
-        return indentation + lines.replace(newLine, newLine + indentation);
-    }
-
-    /**
      * Formats the values in a frame as a tabulated string.
      *
      * @param frame
@@ -395,50 +175,6 @@
     }
 
     /**
-     * Convenient shortcut for calling {@link #appendLocation(StringBuilder, JavaMethod, int)} without having to supply a
-     * a {@link StringBuilder} instance and convert the result to a string.
-     */
-    public static String toLocation(ResolvedJavaMethod method, int bci) {
-        return appendLocation(new StringBuilder(), method, bci).toString();
-    }
-
-    /**
-     * Appends a string representation of a location specified by a given method and bci to a given
-     * {@link StringBuilder}. If a stack trace element with a non-null file name and non-negative line number is
-     * {@linkplain JavaMethod#toStackTraceElement(int) available} for the given method, then the string returned is the
-     * {@link StackTraceElement#toString()} value of the stack trace element, suffixed by the bci location. For example:
-     *
-     * <pre>
-     *     java.lang.String.valueOf(String.java:2930) [bci: 12]
-     * </pre>
-     *
-     * Otherwise, the string returned is the value of {@code CiUtil.format("%H.%n(%p)"}, suffixed by the bci location.
-     * For example:
-     *
-     * <pre>
-     *     java.lang.String.valueOf(int) [bci: 12]
-     * </pre>
-     *
-     * @param sb
-     * @param method
-     * @param bci
-     * @return
-     */
-    public static StringBuilder appendLocation(StringBuilder sb, ResolvedJavaMethod method, int bci) {
-        if (method != null) {
-            StackTraceElement ste = method.toStackTraceElement(bci);
-            if (ste.getFileName() != null && ste.getLineNumber() > 0) {
-                sb.append(ste);
-            } else {
-                sb.append(CodeUtil.format("%H.%n(%p)", method));
-            }
-        } else {
-            sb.append("Null method");
-        }
-        return sb.append(" [bci: ").append(bci).append(']');
-    }
-
-    /**
      * Appends a formatted code position to a {@link StringBuilder}.
      *
      * @param sb the {@link StringBuilder} to append to
@@ -446,7 +182,7 @@
      * @return the value of {@code sb}
      */
     public static StringBuilder append(StringBuilder sb, BytecodePosition pos) {
-        appendLocation(sb.append("at "), pos.getMethod(), pos.getBCI());
+        MetaUtil.appendLocation(sb.append("at "), pos.getMethod(), pos.getBCI());
         if (pos.getCaller() != null) {
             sb.append(NEW_LINE);
             append(sb, pos.getCaller());
@@ -462,7 +198,7 @@
      * @return the value of {@code sb}
      */
     public static StringBuilder append(StringBuilder sb, BytecodeFrame frame) {
-        appendLocation(sb.append("at "), frame.getMethod(), frame.getBCI());
+        MetaUtil.appendLocation(sb.append("at "), frame.getMethod(), frame.getBCI());
         if (frame.values != null && frame.values.length > 0) {
             sb.append(NEW_LINE);
             String table = tabulateValues(frame);
@@ -568,103 +304,4 @@
         }
         return sb;
     }
-
-    public static Kind[] signatureToKinds(ResolvedJavaMethod method) {
-        Kind receiver = isStatic(method.accessFlags()) ? null : method.holder().kind();
-        return signatureToKinds(method.signature(), receiver);
-    }
-
-    public static Kind[] signatureToKinds(Signature signature, Kind receiverKind) {
-        int args = signature.argumentCount(false);
-        Kind[] result;
-        int i = 0;
-        if (receiverKind != null) {
-            result = new Kind[args + 1];
-            result[0] = receiverKind;
-            i = 1;
-        } else {
-            result = new Kind[args];
-        }
-        for (int j = 0; j < args; j++) {
-            result[i + j] = signature.argumentKindAt(j);
-        }
-        return result;
-    }
-
-    public static Class< ? >[] signatureToTypes(Signature signature, ResolvedJavaType accessingClass) {
-        int count = signature.argumentCount(false);
-        Class< ? >[] result = new Class< ? >[count];
-        for (int i = 0; i < result.length; ++i) {
-            result[i] = signature.argumentTypeAt(i, accessingClass).resolve(accessingClass).toJava();
-        }
-        return result;
-    }
-
-    /**
-     * Formats some profiling information associated as a string.
-     *
-     * @param info the profiling info to format
-     * @param method an optional method that augments the profile string returned
-     * @param sep the separator to use for each separate profile record
-     */
-    public static String profileToString(ProfilingInfo info, ResolvedJavaMethod method, String sep) {
-        StringBuilder buf = new StringBuilder(100);
-        if (method != null) {
-            buf.append(String.format("canBeStaticallyBound: %b%s", method.canBeStaticallyBound(), sep)).
-            append(String.format("invocationCount: %d%s", method.invocationCount(), sep));
-        }
-        for (int i = 0; i < info.codeSize(); i++) {
-            if (info.getExecutionCount(i) != -1) {
-                buf.append(String.format("executionCount@%d: %d%s", i, info.getExecutionCount(i), sep));
-            }
-
-            if (info.getBranchTakenProbability(i) != -1) {
-                buf.append(String.format("branchProbability@%d: %.3f%s", i, info.getBranchTakenProbability(i), sep));
-            }
-
-            double[] switchProbabilities = info.getSwitchProbabilities(i);
-            if (switchProbabilities != null) {
-                buf.append(String.format("switchProbabilities@%d:", i));
-                for (int j = 0; j < switchProbabilities.length; j++) {
-                    buf.append(String.format(" %.3f", switchProbabilities[j]));
-                }
-                buf.append(sep);
-            }
-
-            if (info.getExceptionSeen(i) != ExceptionSeen.FALSE) {
-                buf.append(String.format("exceptionSeen@%d: %s%s", i, info.getExceptionSeen(i).name(), sep));
-            }
-
-            JavaTypeProfile typeProfile = info.getTypeProfile(i);
-            if (typeProfile != null) {
-                ProfiledType[] ptypes = typeProfile.getTypes();
-                if (ptypes != null) {
-                    buf.append(String.format("types@%d:", i));
-                    for (int j = 0; j < ptypes.length; j++) {
-                        ProfiledType ptype = ptypes[j];
-                        buf.append(String.format(" %.3f (%s)%s", ptype.probability, ptype.type, sep));
-                    }
-                    buf.append(String.format(" %.3f <not recorded>%s", typeProfile.getNotRecordedProbability(), sep));
-                }
-            }
-        }
-
-        boolean firstDeoptReason = true;
-        for (DeoptimizationReason reason: DeoptimizationReason.values()) {
-            int count = info.getDeoptimizationCount(reason);
-            if (count > 0) {
-                if (firstDeoptReason) {
-                    buf.append("deoptimization history").append(sep);
-                    firstDeoptReason = false;
-                }
-                buf.append(String.format(" %s: %d%s", reason.name(), count, sep));
-            }
-        }
-        if (buf.length() == 0) {
-            return "";
-        }
-        String s = buf.toString();
-        assert s.endsWith(sep);
-        return s.substring(0, s.length() - sep.length());
-    }
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Tue Jul 03 11:16:56 2012 +0200
@@ -29,8 +29,7 @@
 
 /**
  * Represents the output from compiling a method, including the compiled machine code, associated data and references,
- * relocation information, deoptimization information, etc. It is the essential component of a {@link CiResult}, which also includes
- * {@linkplain CiStatistics compilation statistics} and {@linkplain BailoutException failure information}.
+ * relocation information, deoptimization information, etc.
  */
 public class CompilationResult implements Serializable {
 
@@ -403,7 +402,6 @@
      *
      * @param codePos  the position in the code that is covered by the handler
      * @param handlerPos    the position of the handler
-     * @param throwableType the type of exceptions handled by the handler
      */
     public void recordExceptionHandler(int codePos, int handlerPos) {
         getExceptionHandlers().add(new ExceptionHandler(codePos, handlerPos));
@@ -521,7 +519,7 @@
             appendRefMap(sb, "registerMap", info.getRegisterRefMap());
             BytecodePosition codePos = info.getBytecodePosition();
             if (codePos != null) {
-                CodeUtil.appendLocation(sb.append(" "), codePos.getMethod(), codePos.getBCI());
+                MetaUtil.appendLocation(sb.append(" "), codePos.getMethod(), codePos.getBCI());
                 if (info.hasFrame()) {
                     sb.append(" #locals=").append(info.frame().numLocals).append(" #expr=").append(info.frame().numStack);
                     if (info.frame().numLocks > 0) {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Tue Jul 03 11:16:56 2012 +0200
@@ -75,7 +75,7 @@
     /**
      * Gets the deoptimization information for each inlined frame (if available).
      *
-     * @return {@code null} if no frame de-opt info is {@linkplain #hasDebugFrame available}
+     * @return {@code null} if no frame de-opt info is {@linkplain #hasFrame() available}
      */
     public BytecodeFrame frame() {
         if (hasFrame()) {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java	Tue Jul 03 11:16:56 2012 +0200
@@ -62,7 +62,7 @@
      *
      * @param type the type of calling convention
      * @param flag specifies whether registers for {@linkplain RegisterFlag#CPU integral} or
-     *             {@linkplain} RegisterFlag#FPU floating point} parameters are being requested
+     *             {@linkplain RegisterFlag#FPU floating point} parameters are being requested
      * @return the ordered set of registers that may be used to pass parameters in a call conforming to {@code type}
      */
     Register[] getCallingConventionRegisters(Type type, RegisterFlag flag);
@@ -77,7 +77,7 @@
      * {@linkplain Register#categorize(Register[]) categorized} by register {@linkplain RegisterFlag flags}.
      *
      * @return a map from each {@link RegisterFlag} constant to the list of {@linkplain #getAllocatableRegisters()
-     *         allocatable} registers for which the flag is {@linkplain #isSet(RegisterFlag) set}
+     *         allocatable} registers for which the flag is set
      *
      */
     EnumMap<RegisterFlag, Register[]> getCategorizedAllocatableRegisters();
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java	Tue Jul 03 11:16:56 2012 +0200
@@ -35,7 +35,7 @@
     private final Register reg;
 
     /**
-     * Should only be called from {@link Register#CiRegister} to ensure canonicalization.
+     * Should only be called from {@link Register#Register} to ensure canonicalization.
      */
     protected RegisterValue(Kind kind, Register register) {
         super(kind);
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java	Tue Jul 03 11:16:56 2012 +0200
@@ -42,7 +42,7 @@
      *
      * @param kind The kind of the value stored in the stack slot.
      * @param offset The offset of the stack slot (in bytes)
-     * @param inCallerFrame Specifies if the offset is relative to the stack pointer,
+     * @param addFrameSize Specifies if the offset is relative to the stack pointer,
      *        or the beginning of the frame (stack pointer + total frame size).
      */
     public static StackSlot get(Kind kind, int offset, boolean addFrameSize) {
@@ -71,7 +71,7 @@
     }
 
     /**
-     * Private constructor to enforce use of {@link #get()} so that a cache can be used.
+     * Private constructor to enforce use of {@link #get(Kind, int, boolean)} so that a cache can be used.
      */
     private StackSlot(Kind kind, int offset, boolean addFrameSize) {
         super(kind);
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java	Tue Jul 03 11:16:56 2012 +0200
@@ -70,7 +70,7 @@
     public final int stackAlignment;
 
     /**
-     * @see http://docs.sun.com/app/docs/doc/806-0477/6j9r2e2b9?a=view
+     * @see "http://docs.oracle.com/cd/E19455-01/806-0477/overview-4/index.html"
      */
     public final int stackBias;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,110 @@
+/*
+ * 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.api.code;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.JavaTypeProfile.*;
+
+/**
+ * Utility for deriving hint types for a type check instruction (e.g. checkcast or instanceof)
+ * based on the target type of the check and any profiling information available for the instruction.
+ */
+public class TypeCheckHints {
+
+    private static final ResolvedJavaType[] NO_TYPES = {};
+
+    /**
+     * If true, then {@link #types} contains the only possible type that could pass the type check
+     * because the target of the type check is a final class or has been speculated to be a final class.
+     */
+    public final boolean exact;
+
+    /**
+     * The most likely types that the type check instruction will see.
+     */
+    public final ResolvedJavaType[] types;
+
+    /**
+     * Derives hint information for use when generating the code for a type check instruction.
+     *
+     * @param type the target type of the type check
+     * @param profile the profiling information available for the instruction (if any)
+     * @param assumptions the object in which speculations are recorded. This is null if speculations are not supported.
+     * @param minHintHitProbability if the probability that the type check will hit one the profiled types (up to
+     *            {@code maxHints}) is below this value, then {@link #types} will be null
+     * @param maxHints the maximum length of {@link #types}
+     */
+    public TypeCheckHints(ResolvedJavaType type, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) {
+        if (type != null && isFinalClass(type)) {
+            types = new ResolvedJavaType[] {type};
+            exact = true;
+        } else {
+            ResolvedJavaType uniqueSubtype = type == null ? null : type.uniqueConcreteSubtype();
+            if (uniqueSubtype != null) {
+                types = new ResolvedJavaType[] {uniqueSubtype};
+                if (assumptions != null) {
+                    assumptions.recordConcreteSubtype(type, uniqueSubtype);
+                    exact = true;
+                } else {
+                    exact = false;
+                }
+            } else {
+                exact = false;
+                ResolvedJavaType[] hintTypes = NO_TYPES;
+                JavaTypeProfile typeProfile = profile;
+                if (typeProfile != null) {
+                    double notRecordedTypes = typeProfile.getNotRecordedProbability();
+                    ProfiledType[] ptypes = typeProfile.getTypes();
+                    if (notRecordedTypes < (1D - minHintHitProbability) && ptypes != null && ptypes.length > 0) {
+                        hintTypes = new ResolvedJavaType[ptypes.length];
+                        int hintCount = 0;
+                        double totalHintProbability = 0.0d;
+                        for (ProfiledType ptype : ptypes) {
+                            ResolvedJavaType hint = ptype.type;
+                            if (type != null && hint.isSubtypeOf(type)) {
+                                hintTypes[hintCount++] = hint;
+                                totalHintProbability += ptype.probability;
+                            }
+                        }
+                        if (totalHintProbability >= minHintHitProbability) {
+                            if (hintTypes.length != hintCount || hintCount > maxHints) {
+                                hintTypes = Arrays.copyOf(hintTypes, Math.min(maxHints, hintCount));
+                            }
+                        } else {
+                            hintTypes = NO_TYPES;
+                        }
+
+                    }
+                }
+                this.types = hintTypes;
+            }
+        }
+    }
+
+    public static boolean isFinalClass(ResolvedJavaType type) {
+        return Modifier.isFinal(type.accessFlags()) || (type.isArrayClass() && Modifier.isFinal(type.componentType().accessFlags()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.interpreter/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.api.interpreter</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.api.meta</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Tue Jul 03 11:16:56 2012 +0200
@@ -25,7 +25,7 @@
 /**
  * Represents a constant (boxed) value, such as an integer, floating point number, or object reference,
  * within the compiler and across the compiler/runtime interface. Exports a set of {@code Constant}
- * instances that represent frequently used constant values, such as {@link #ZERO}.
+ * instances that represent frequently used constant values, such as {@link #NULL_OBJECT}.
  */
 public final class Constant extends Value {
     private static final long serialVersionUID = -6355452536852663986L;
@@ -262,7 +262,6 @@
 
     /**
      * Unchecked access to a primitive value.
-     * @return
      */
     public long asPrimitive() {
         if (kind.isObject()) {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Tue Jul 03 11:16:56 2012 +0200
@@ -41,8 +41,7 @@
     /**
      * Looks up a reference to a field. If {@code opcode} is non-negative, then resolution checks
      * specific to the JVM instruction it denotes are performed if the field is already resolved.
-     * Should any of these checks fail, an {@linkplain JavaField#isResolved() unresolved}
-     * field reference is returned.
+     * Should any of these checks fail, an unresolved field reference is returned.
      *
      * @param cpi the constant pool index
      * @param opcode the opcode of the instruction for which the lookup is being performed or {@code -1}
@@ -54,8 +53,7 @@
     /**
      * Looks up a reference to a method. If {@code opcode} is non-negative, then resolution checks
      * specific to the JVM instruction it denotes are performed if the method is already resolved.
-     * Should any of these checks fail, an {@linkplain JavaMethod#isResolved() unresolved}
-     * method reference is returned.
+     * Should any of these checks fail, an unresolved method reference is returned.
      *
      * @param cpi the constant pool index
      * @param opcode the opcode of the instruction for which the lookup is being performed or {@code -1}
@@ -67,8 +65,7 @@
     /**
      * Looks up a reference to a type. If {@code opcode} is non-negative, then resolution checks
      * specific to the JVM instruction it denotes are performed if the type is already resolved.
-     * Should any of these checks fail, an {@linkplain JavaType#isResolved() unresolved}
-     * type reference is returned.
+     * Should any of these checks fail, an unresolved type reference is returned.
      *
      * @param cpi the constant pool index
      * @param opcode the opcode of the instruction for which the lookup is being performed or {@code -1}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,85 @@
+/*
+ * 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.api.meta;
+
+
+/**
+ * An implementation of {@link ProfilingInfo} that can used in the absence of real profile information.
+ */
+public final class DefaultProfilingInfo implements ProfilingInfo {
+    private static final ProfilingInfo[] NO_PROFILING_INFO = new ProfilingInfo[] {
+        new DefaultProfilingInfo(ExceptionSeen.TRUE),
+        new DefaultProfilingInfo(ExceptionSeen.FALSE),
+        new DefaultProfilingInfo(ExceptionSeen.NOT_SUPPORTED)
+    };
+
+    private final ExceptionSeen exceptionSeen;
+
+    DefaultProfilingInfo(ExceptionSeen exceptionSeen) {
+        this.exceptionSeen = exceptionSeen;
+    }
+
+    @Override
+    public int codeSize() {
+        return 0;
+    }
+
+    @Override
+    public JavaTypeProfile getTypeProfile(int bci) {
+        return null;
+    }
+
+    @Override
+    public double getBranchTakenProbability(int bci) {
+        return -1;
+    }
+
+    @Override
+    public double[] getSwitchProbabilities(int bci) {
+        return null;
+    }
+
+    @Override
+    public ExceptionSeen getExceptionSeen(int bci) {
+        return exceptionSeen;
+    }
+
+    @Override
+    public int getExecutionCount(int bci) {
+        return -1;
+    }
+
+    public static ProfilingInfo get(ExceptionSeen exceptionSeen) {
+        return NO_PROFILING_INFO[exceptionSeen.ordinal()];
+    }
+
+    @Override
+    public int getDeoptimizationCount(DeoptimizationReason reason) {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        return "BaseProfilingInfo<" + MetaUtil.profileToString(this, null, "; ") + ">";
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,8 +22,18 @@
  */
 package com.oracle.graal.api.meta;
 
+import static java.lang.reflect.Modifier.*;
 
+import java.lang.annotation.*;
+import java.util.*;
+
+import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
+
+/**
+ * Miscellaneous collection of utility methods used by {@code com.oracle.graal.api.meta} and its clients.
+ */
 public class MetaUtil {
+
     /**
      * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for anonymous and local
      * classes.
@@ -76,16 +86,16 @@
      *         boolean[][]
      * </pre>
      *
-     * @param riType the type to be converted to a Java name
+     * @param type the type to be converted to a Java name
      * @param qualified specifies if the package prefix of the type should be included in the returned name
-     * @return the Java name corresponding to {@code riType}
+     * @return the Java name corresponding to {@code type}
      */
-    public static String toJavaName(JavaType riType, boolean qualified) {
-        Kind kind = riType.kind();
+    public static String toJavaName(JavaType type, boolean qualified) {
+        Kind kind = type.kind();
         if (kind.isObject()) {
-            return internalNameToJava(riType.name(), qualified);
+            return internalNameToJava(type.name(), qualified);
         }
-        return riType.kind().javaName;
+        return type.kind().javaName;
     }
 
     /**
@@ -98,11 +108,11 @@
      *      boolean[][]
      * </pre>
      *
-     * @param riType the type to be converted to a Java name
-     * @return the Java name corresponding to {@code riType}
+     * @param type the type to be converted to a Java name
+     * @return the Java name corresponding to {@code type}
      */
-    public static String toJavaName(JavaType riType) {
-        return (riType == null) ? null : internalNameToJava(riType.name(), true);
+    public static String toJavaName(JavaType type) {
+        return (type == null) ? null : internalNameToJava(type.name(), true);
     }
 
     public static String internalNameToJava(String name, boolean qualified) {
@@ -127,4 +137,369 @@
                 return Kind.fromPrimitiveOrVoidTypeChar(name.charAt(0)).javaName;
         }
     }
+
+
+    /**
+     * Gets a string for a given method formatted according to a given format specification. A format specification is
+     * composed of characters that are to be copied verbatim to the result and specifiers that denote an attribute of
+     * the method that is to be copied to the result. A specifier is a single character preceded by a '%' character. The
+     * accepted specifiers and the method attributes they denote are described below:
+     *
+     * <pre>
+     *     Specifier | Description                                          | Example(s)
+     *     ----------+------------------------------------------------------------------------------------------
+     *     'R'       | Qualified return type                                | "int" "java.lang.String"
+     *     'r'       | Unqualified return type                              | "int" "String"
+     *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
+     *     'h'       | Unqualified holder                                   | "Entry"
+     *     'n'       | Method name                                          | "add"
+     *     'P'       | Qualified parameter types, separated by ', '         | "int, java.lang.String"
+     *     'p'       | Unqualified parameter types, separated by ', '       | "int, String"
+     *     'f'       | Indicator if method is unresolved, static or virtual | "unresolved" "static" "virtual"
+     *     '%'       | A '%' character                                      | "%"
+     * </pre>
+     *
+     * @param format a format specification
+     * @param method the method to be formatted
+     * @return the result of formatting this method according to {@code format}
+     * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
+     */
+    public static String format(String format, JavaMethod method) throws IllegalFormatException {
+        final StringBuilder sb = new StringBuilder();
+        int index = 0;
+        Signature sig = null;
+        while (index < format.length()) {
+            final char ch = format.charAt(index++);
+            if (ch == '%') {
+                if (index >= format.length()) {
+                    throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a method format specification");
+                }
+                final char specifier = format.charAt(index++);
+                boolean qualified = false;
+                switch (specifier) {
+                    case 'R':
+                        qualified = true;
+                        // fall through
+                    case 'r': {
+                        if (sig == null) {
+                            sig = method.signature();
+                        }
+                        sb.append(toJavaName(sig.returnType(null), qualified));
+                        break;
+                    }
+                    case 'H':
+                        qualified = true;
+                        // fall through
+                    case 'h': {
+                        sb.append(toJavaName(method.holder(), qualified));
+                        break;
+                    }
+                    case 'n': {
+                        sb.append(method.name());
+                        break;
+                    }
+                    case 'P':
+                        qualified = true;
+                        // fall through
+                    case 'p': {
+                        if (sig == null) {
+                            sig = method.signature();
+                        }
+                        for (int i = 0; i < sig.argumentCount(false); i++) {
+                            if (i != 0) {
+                                sb.append(", ");
+                            }
+                            sb.append(toJavaName(sig.argumentTypeAt(i, null), qualified));
+                        }
+                        break;
+                    }
+                    case 'f': {
+                        sb.append(!(method instanceof ResolvedJavaMethod) ? "unresolved" : isStatic(((ResolvedJavaMethod) method).accessFlags()) ? "static" : "virtual");
+                        break;
+                    }
+                    case '%': {
+                        sb.append('%');
+                        break;
+                    }
+                    default: {
+                        throw new UnknownFormatConversionException(String.valueOf(specifier));
+                    }
+                }
+            } else {
+                sb.append(ch);
+            }
+        }
+        return sb.toString();
+    }
+
+
+    /**
+     * Gets a string for a given field formatted according to a given format specification. A format specification is
+     * composed of characters that are to be copied verbatim to the result and specifiers that denote an attribute of
+     * the field that is to be copied to the result. A specifier is a single character preceded by a '%' character. The
+     * accepted specifiers and the field attributes they denote are described below:
+     *
+     * <pre>
+     *     Specifier | Description                                          | Example(s)
+     *     ----------+------------------------------------------------------------------------------------------
+     *     'T'       | Qualified type                                       | "int" "java.lang.String"
+     *     't'       | Unqualified type                                     | "int" "String"
+     *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
+     *     'h'       | Unqualified holder                                   | "Entry"
+     *     'n'       | Field name                                           | "age"
+     *     'f'       | Indicator if field is unresolved, static or instance | "unresolved" "static" "instance"
+     *     '%'       | A '%' character                                      | "%"
+     * </pre>
+     *
+     * @param format a format specification
+     * @param field the field to be formatted
+     * @return the result of formatting this field according to {@code format}
+     * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
+     */
+    public static String format(String format, JavaField field) throws IllegalFormatException {
+        final StringBuilder sb = new StringBuilder();
+        int index = 0;
+        JavaType type = field.type();
+        while (index < format.length()) {
+            final char ch = format.charAt(index++);
+            if (ch == '%') {
+                if (index >= format.length()) {
+                    throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a field format specification");
+                }
+                final char specifier = format.charAt(index++);
+                boolean qualified = false;
+                switch (specifier) {
+                    case 'T':
+                        qualified = true;
+                        // fall through
+                    case 't': {
+                        sb.append(toJavaName(type, qualified));
+                        break;
+                    }
+                    case 'H':
+                        qualified = true;
+                        // fall through
+                    case 'h': {
+                        sb.append(toJavaName(field.holder(), qualified));
+                        break;
+                    }
+                    case 'n': {
+                        sb.append(field.name());
+                        break;
+                    }
+                    case 'f': {
+                        sb.append(!(field instanceof ResolvedJavaField) ? "unresolved" : isStatic(((ResolvedJavaField) field).accessFlags()) ? "static" : "instance");
+                        break;
+                    }
+                    case '%': {
+                        sb.append('%');
+                        break;
+                    }
+                    default: {
+                        throw new UnknownFormatConversionException(String.valueOf(specifier));
+                    }
+                }
+            } else {
+                sb.append(ch);
+            }
+        }
+        return sb.toString();
+    }
+
+
+    /**
+     * Gets the annotation of a particular type for a formal parameter of a given method.
+     *
+     * @param annotationClass the Class object corresponding to the annotation type
+     * @param parameterIndex the index of a formal parameter of {@code method}
+     * @param method the method for which a parameter annotation is being requested
+     * @return the annotation of type {@code annotationClass} for the formal parameter present, else null
+     * @throws IndexOutOfBoundsException if {@code parameterIndex} does not denote a formal parameter
+     */
+    public static <T extends Annotation> T getParameterAnnotation(Class<T> annotationClass, int parameterIndex, ResolvedJavaMethod method) {
+        if (parameterIndex >= 0) {
+            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+            for (Annotation a : parameterAnnotations[parameterIndex]) {
+                if (a.annotationType() == annotationClass) {
+                    return annotationClass.cast(a);
+                }
+            }
+        }
+        return null;
+    }
+
+
+    /**
+     * Convenient shortcut for calling {@link #appendLocation(StringBuilder, ResolvedJavaMethod, int)} without having to supply a
+     * a {@link StringBuilder} instance and convert the result to a string.
+     */
+    public static String toLocation(ResolvedJavaMethod method, int bci) {
+        return appendLocation(new StringBuilder(), method, bci).toString();
+    }
+
+
+    /**
+     * Appends a string representation of a location specified by a given method and bci to a given
+     * {@link StringBuilder}. If a stack trace element with a non-null file name and non-negative line number is
+     * {@linkplain ResolvedJavaMethod#toStackTraceElement(int) available} for the given method, then the string returned is the
+     * {@link StackTraceElement#toString()} value of the stack trace element, suffixed by the bci location. For example:
+     *
+     * <pre>
+     *     java.lang.String.valueOf(String.java:2930) [bci: 12]
+     * </pre>
+     *
+     * Otherwise, the string returned is the value of {@code CiUtil.format("%H.%n(%p)"}, suffixed by the bci location.
+     * For example:
+     *
+     * <pre>
+     *     java.lang.String.valueOf(int) [bci: 12]
+     * </pre>
+     *
+     * @param sb
+     * @param method
+     * @param bci
+     */
+    public static StringBuilder appendLocation(StringBuilder sb, ResolvedJavaMethod method, int bci) {
+        if (method != null) {
+            StackTraceElement ste = method.toStackTraceElement(bci);
+            if (ste.getFileName() != null && ste.getLineNumber() > 0) {
+                sb.append(ste);
+            } else {
+                sb.append(format("%H.%n(%p)", method));
+            }
+        } else {
+            sb.append("Null method");
+        }
+        return sb.append(" [bci: ").append(bci).append(']');
+    }
+
+
+    public static Kind[] signatureToKinds(ResolvedJavaMethod method) {
+        Kind receiver = isStatic(method.accessFlags()) ? null : method.holder().kind();
+        return signatureToKinds(method.signature(), receiver);
+    }
+
+
+    public static Kind[] signatureToKinds(Signature signature, Kind receiverKind) {
+        int args = signature.argumentCount(false);
+        Kind[] result;
+        int i = 0;
+        if (receiverKind != null) {
+            result = new Kind[args + 1];
+            result[0] = receiverKind;
+            i = 1;
+        } else {
+            result = new Kind[args];
+        }
+        for (int j = 0; j < args; j++) {
+            result[i + j] = signature.argumentKindAt(j);
+        }
+        return result;
+    }
+
+
+    public static Class< ? >[] signatureToTypes(Signature signature, ResolvedJavaType accessingClass) {
+        int count = signature.argumentCount(false);
+        Class< ? >[] result = new Class< ? >[count];
+        for (int i = 0; i < result.length; ++i) {
+            result[i] = signature.argumentTypeAt(i, accessingClass).resolve(accessingClass).toJava();
+        }
+        return result;
+    }
+
+
+    /**
+     * Formats some profiling information associated as a string.
+     *
+     * @param info the profiling info to format
+     * @param method an optional method that augments the profile string returned
+     * @param sep the separator to use for each separate profile record
+     */
+    public static String profileToString(ProfilingInfo info, ResolvedJavaMethod method, String sep) {
+        StringBuilder buf = new StringBuilder(100);
+        if (method != null) {
+            buf.append(String.format("canBeStaticallyBound: %b%s", method.canBeStaticallyBound(), sep)).
+            append(String.format("invocationCount: %d%s", method.invocationCount(), sep));
+        }
+        for (int i = 0; i < info.codeSize(); i++) {
+            if (info.getExecutionCount(i) != -1) {
+                buf.append(String.format("executionCount@%d: %d%s", i, info.getExecutionCount(i), sep));
+            }
+
+            if (info.getBranchTakenProbability(i) != -1) {
+                buf.append(String.format("branchProbability@%d: %.3f%s", i, info.getBranchTakenProbability(i), sep));
+            }
+
+            double[] switchProbabilities = info.getSwitchProbabilities(i);
+            if (switchProbabilities != null) {
+                buf.append(String.format("switchProbabilities@%d:", i));
+                for (int j = 0; j < switchProbabilities.length; j++) {
+                    buf.append(String.format(" %.3f", switchProbabilities[j]));
+                }
+                buf.append(sep);
+            }
+
+            if (info.getExceptionSeen(i) != ExceptionSeen.FALSE) {
+                buf.append(String.format("exceptionSeen@%d: %s%s", i, info.getExceptionSeen(i).name(), sep));
+            }
+
+            JavaTypeProfile typeProfile = info.getTypeProfile(i);
+            if (typeProfile != null) {
+                ProfiledType[] ptypes = typeProfile.getTypes();
+                if (ptypes != null) {
+                    buf.append(String.format("types@%d:", i));
+                    for (int j = 0; j < ptypes.length; j++) {
+                        ProfiledType ptype = ptypes[j];
+                        buf.append(String.format(" %.3f (%s)%s", ptype.probability, ptype.type, sep));
+                    }
+                    buf.append(String.format(" %.3f <not recorded>%s", typeProfile.getNotRecordedProbability(), sep));
+                }
+            }
+        }
+
+        boolean firstDeoptReason = true;
+        for (DeoptimizationReason reason: DeoptimizationReason.values()) {
+            int count = info.getDeoptimizationCount(reason);
+            if (count > 0) {
+                if (firstDeoptReason) {
+                    buf.append("deoptimization history").append(sep);
+                    firstDeoptReason = false;
+                }
+                buf.append(String.format(" %s: %d%s", reason.name(), count, sep));
+            }
+        }
+        if (buf.length() == 0) {
+            return "";
+        }
+        String s = buf.toString();
+        assert s.endsWith(sep);
+        return s.substring(0, s.length() - sep.length());
+    }
+
+
+    /**
+     * Converts a Java source-language class name into the internal form.
+     *
+     * @param className the class name
+     * @return the internal name form of the class name
+     */
+    public static String toInternalName(String className) {
+        return "L" + className.replace('.', '/') + ";";
+    }
+
+
+    /**
+     * Prepends the String {@code indentation} to every line in String {@code lines}, including a possibly non-empty
+     * line following the final newline.
+     */
+    public static String indent(String lines, String indentation) {
+        if (lines.length() == 0) {
+            return lines;
+        }
+        final String newLine = "\n";
+        if (lines.endsWith(newLine)) {
+            return indentation + (lines.substring(0, lines.length() - 1)).replace(newLine, newLine + indentation) + newLine;
+        }
+        return indentation + lines.replace(newLine, newLine + indentation);
+    }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Tue Jul 03 11:16:56 2012 +0200
@@ -33,14 +33,14 @@
 public interface ResolvedJavaMethod extends JavaMethod {
 
     /**
-     * Gets the bytecode of the method, if the method {@linkplain #isResolved()} and has code.
+     * Gets the bytecode of the method, if the method has code.
      * The returned byte array does not contain breakpoints or non-Java bytecodes.
      * @return the bytecode of the method or {@code null} if none is available
      */
     byte[] code();
 
     /**
-     * Gets the size of the bytecode of the method, if the method {@linkplain #isResolved()} and has code.
+     * Gets the size of the bytecode of the method, if the method has code.
      * @return the size of the bytecode in bytes, or 0 if no bytecode is available
      */
     int codeSize();
@@ -165,7 +165,6 @@
      * parameters, in declaration order, of this method.
      *
      * @see Method#getParameterAnnotations()
-     * @see CiUtil#getParameterAnnotation(int, JavaResolvedMethod)
      */
     Annotation[][] getParameterAnnotations();
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Tue Jul 03 11:16:56 2012 +0200
@@ -149,8 +149,8 @@
      * such concrete method or more than one such method exists. Returns the method a
      * if a is a concrete method that is not overridden. If the compiler uses the
      * result of this method for its compilation, it must register an assumption
-     * (see {@link CiAssumptions}), because dynamic class loading can invalidate
-     * the result of this method.
+     * because dynamic class loading can invalidate the result of this method.
+     *
      * @param method the method a for which a unique concrete target is searched
      * @return the unique concrete target or {@code null} if no such target exists
      *         or assumptions are not supported by this runtime
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Signature.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Signature.java	Tue Jul 03 11:16:56 2012 +0200
@@ -38,7 +38,7 @@
 
     /**
      * Gets the argument type at the specified position. This method will return a
-     * {@linkplain JavaType#isResolved() resolved} type if possible but without
+     * {@linkplain ResolvedJavaType resolved} type if possible but without
      * triggering any class loading or resolution.
      *
      * @param index the index into the parameters, with {@code 0} indicating the first parameter
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/UnresolvedField.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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.graal.api.meta;
+
+
+/**
+ * A implementation of {@link JavaField} for an unresolved field.
+ */
+public class UnresolvedField implements JavaField {
+
+    public final String name;
+    public final JavaType holder;
+    public final JavaType type;
+
+    public UnresolvedField(JavaType holder, String name, JavaType type) {
+        this.name = name;
+        this.type = type;
+        this.holder = holder;
+    }
+
+    public String name() {
+        return name;
+    }
+
+    public JavaType type() {
+        return type;
+    }
+
+    public Kind kind() {
+        return type.kind();
+    }
+
+    public JavaType holder() {
+        return holder;
+    }
+
+    @Override
+    public int hashCode() {
+        return System.identityHashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o == this;
+    }
+
+    /**
+     * Converts this compiler interface field to a string.
+     */
+    @Override
+    public String toString() {
+        return MetaUtil.format("%H.%n [unresolved]", this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/UnresolvedMethod.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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.graal.api.meta;
+
+
+/**
+ * A implementation of {@link JavaMethod} for an unresolved method.
+ */
+public class UnresolvedMethod implements JavaMethod {
+
+    public final String name;
+    public final JavaType holder;
+    public final Signature signature;
+
+    public UnresolvedMethod(JavaType holder, String name, Signature signature) {
+        this.name = name;
+        this.holder = holder;
+        this.signature = signature;
+    }
+
+    public String name() {
+        return name;
+    }
+
+    public JavaType holder() {
+        return holder;
+    }
+
+    public Signature signature() {
+        return signature;
+    }
+
+    @Override
+    public int hashCode() {
+        return System.identityHashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o == this;
+    }
+
+    @Override
+    public String toString() {
+        return MetaUtil.format("%H.%n(%p) [unresolved]", this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.test/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.api.test</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.api</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot.test/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.boot.test</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.boot</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.bytecode/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.bytecode</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeLookupSwitch.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeLookupSwitch.java	Tue Jul 03 11:16:56 2012 +0200
@@ -41,11 +41,6 @@
     }
 
     @Override
-    public int defaultOffset() {
-        return stream.readInt(alignedBci);
-    }
-
-    @Override
     public int offsetAt(int i) {
         return stream.readInt(alignedBci + OFFSET_TO_FIRST_PAIR_OFFSET + PAIR_SIZE * i);
     }
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeSwitch.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeSwitch.java	Tue Jul 03 11:16:56 2012 +0200
@@ -80,7 +80,9 @@
      * Gets the offset from the start of the switch instruction to the default switch target.
      * @return the offset to the default switch target
      */
-    public abstract int defaultOffset();
+    public int defaultOffset() {
+        return stream.readInt(alignedBci);
+    }
 
     /**
      * Gets the key at {@code i}'th switch target index.
@@ -107,4 +109,5 @@
      * @return the total size in bytes of the switch instruction
      */
     public abstract int size();
+
 }
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeTableSwitch.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeTableSwitch.java	Tue Jul 03 11:16:56 2012 +0200
@@ -62,11 +62,6 @@
     }
 
     @Override
-    public int defaultOffset() {
-        return stream.readInt(alignedBci);
-    }
-
-    @Override
     public int offsetAt(int i) {
         return stream.readInt(alignedBci + OFFSET_TO_FIRST_JUMP_OFFSET + JUMP_OFFSET_SIZE * i);
     }
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/Bytecodes.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/Bytecodes.java	Tue Jul 03 11:16:56 2012 +0200
@@ -812,7 +812,6 @@
      *
      * @param name instruction name (should be lower case)
      * @param format encodes the length of the instruction
-     * @param flagsArray the set of {@link Flags} associated with the instruction
      */
     private static void def(int opcode, String name, String format, int compilationComplexity) {
         def(opcode, name, format, compilationComplexity, 0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.compiler</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Jul 03 11:16:56 2012 +0200
@@ -36,12 +36,12 @@
 import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.compiler.types.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.max.cri.xir.*;
 
 public class GraalCompiler {
@@ -54,7 +54,7 @@
     /**
      * The runtime that this compiler has been configured for.
      */
-    public final ExtendedRiRuntime runtime;
+    public final GraalCodeCacheProvider runtime;
 
     /**
      * The XIR generator that lowers Java operations to machine operations.
@@ -66,7 +66,7 @@
      */
     public final Backend backend;
 
-    public GraalCompiler(ExtendedRiRuntime runtime, TargetDescription target, Backend backend, RiXirGenerator xirGen) {
+    public GraalCompiler(GraalCodeCacheProvider runtime, TargetDescription target, Backend backend, RiXirGenerator xirGen) {
         this.runtime = runtime;
         this.target = target;
         this.xir = xirGen;
@@ -74,7 +74,7 @@
     }
 
 
-    public CompilationResult compileMethod(final ResolvedJavaMethod method, final StructuredGraph graph, int osrBCI, final RiGraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) {
+    public CompilationResult compileMethod(final ResolvedJavaMethod method, final StructuredGraph graph, int osrBCI, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) {
         assert (method.accessFlags() & Modifier.NATIVE) == 0 : "compiling native methods is not supported";
         if (osrBCI != -1) {
             throw new BailoutException("No OSR supported");
@@ -105,7 +105,7 @@
     /**
      * Builds the graph, optimizes it.
      */
-    public LIR emitHIR(StructuredGraph graph, Assumptions assumptions, RiGraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
+    public LIR emitHIR(StructuredGraph graph, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
 
         if (graph.start().next() == null) {
             plan.runPhases(PhasePosition.AFTER_PARSING, graph);
@@ -149,6 +149,7 @@
             }
         }
 
+        //new ConvertUnreachedToGuardPhase(optimisticOpts).apply(graph);
 
         plan.runPhases(PhasePosition.HIGH_LEVEL, graph);
 
@@ -187,18 +188,17 @@
         if (GraalOptions.CheckCastElimination) {
             new CheckCastEliminationPhase().apply(graph);
         }
+        if (GraalOptions.OptCanonicalizer) {
+            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+        }
+        if (GraalOptions.OptCanonicalizer) {
+            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+        }
 
         if (GraalOptions.OptLoopTransform) {
             new LoopTransformLowPhase().apply(graph);
         }
         new RemoveValueProxyPhase().apply(graph);
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
-        }
-        if (GraalOptions.CheckCastElimination) {
-            new CheckCastEliminationPhase().apply(graph);
-        }
-
 
         plan.runPhases(PhasePosition.MID_LEVEL, graph);
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,11 +22,9 @@
  */
 package com.oracle.graal.compiler;
 
-import com.oracle.max.criutils.TTY.Filter;
 
 /**
  * This class encapsulates options that control the behavior of the Graal compiler.
- * The help message for each option is specified by a {@linkplain #helpMap help map}.
  *
  * (thomaswue) WARNING: Fields of this class are treated as final by Graal.
  */
@@ -99,8 +97,14 @@
     //rematerialize settings
     public static float   MinimumUsageProbability            = 0.95f;
 
-    //loop transform settings
-    public static float   MinimumPeelProbability             = 0.25f;
+    //loop transform settings TODO (gd) tune
+    public static float   MinimumPeelProbability             = 0.35f;
+    public static boolean ReassociateInvariants              = true;
+    public static boolean FullUnroll                         = true;
+    public static int     FullUnrollMaxNodes                 = 150;
+    public static boolean LoopUnswitch                       = ____;
+    public static int     LoopUnswitchMaxIncrease            = 50;
+    public static int     LoopUnswitchUncertaintyBoost       = 5;
 
     // debugging settings
     public static int     MethodEndBreakpointGuards          = 0;
@@ -110,9 +114,6 @@
     public static boolean VerifyPhases                       = true;
     public static boolean CreateDeoptInfo                    = ____;
 
-    /**
-     * See {@link Filter#Filter(String, Object)}.
-     */
     public static String  PrintFilter                        = null;
 
     // printing settings
@@ -183,6 +184,7 @@
     // Translating tableswitch instructions
     public static int     SequentialSwitchLimit              = 4;
     public static int     RangeTestsSwitchDensity            = 5;
+    public static double  MinTableSwitchDensity              = 0.5;
 
     public static boolean DetailedAsserts                    = ____;
 
@@ -208,11 +210,6 @@
     public static boolean OptLoopTransform                   = true;
     public static boolean OptSafepointElimination            = true;
 
-    // Loops
-    public static boolean ReassociateInvariants              = true;
-    public static boolean FullUnroll                         = true;
-    public static int FullUnrollMaxNodes                     = 250; // TODO (gd) tune
-
     /**
      * Insert a counter in the method prologue to track the most frequently called methods that were compiled by Graal.
      */
@@ -267,16 +264,6 @@
     public static String HIRLowerCheckcast = "";
     public static String HIRLowerNewInstance = "";
 
-    /**
-     * The profiling info cache directory.
-     */
-    public static String PICache = null;
-
-    /**
-     * Filters the methods for which profiling info is loaded from/saved to the {@link #PICache}.
-     */
-    public static String PIFilter = null;
-
     static {
         // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
         assert (DetailedAsserts = true) == true;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java	Tue Jul 03 11:16:56 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.max.criutils.*;
@@ -71,7 +70,7 @@
         for (Optimization opt: Optimization.values()) {
             if (!enabledOpts.contains(opt)) {
                 if (GraalOptions.PrintDisabledOptimisticOptimizations) {
-                    TTY.println("WARN: deactivated optimistic optimization %s for %s", opt.name(), CodeUtil.format("%H.%n(%p)", method));
+                    TTY.println("WARN: deactivated optimistic optimization %s for %s", opt.name(), MetaUtil.format("%H.%n(%p)", method));
                 }
                 disabledOptimisticOptsMetric.increment();
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java	Tue Jul 03 11:16:56 2012 +0200
@@ -106,7 +106,7 @@
 
         // block must have exactly one successor
 
-        return instructions.size() == 2 && instructions.get(instructions.size() - 1).info == null;
+        return instructions.size() == 2 && !instructions.get(instructions.size() - 1).hasState();
     }
 
     private void deleteEmptyBlocks(List<Block> code) {
@@ -159,7 +159,7 @@
             if (lastOp instanceof StandardOp.JumpOp) {
                 StandardOp.JumpOp lastJump = (StandardOp.JumpOp) lastOp;
 
-                if (lastOp.info == null) {
+                if (!lastOp.hasState()) {
                     if (lastJump.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel()) {
                         // delete last branch instruction
                         Util.truncate(instructions, instructions.size() - 1);
@@ -169,7 +169,7 @@
                         if (prevOp instanceof StandardOp.BranchOp) {
                             StandardOp.BranchOp prevBranch = (StandardOp.BranchOp) prevOp;
 
-                            if (prevBranch.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel() && prevOp.info == null) {
+                            if (prevBranch.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel() && !prevOp.hasState()) {
                                 // eliminate a conditional branch to the immediate successor
                                 prevBranch.negate(lastJump.destination());
                                 Util.truncate(instructions, instructions.size() - 1);
@@ -178,6 +178,16 @@
                     }
                 }
             }
+            // TODO(ls) enable this optimization
+//            lastOp = instructions.get(instructions.size() - 1);
+//            if (lastOp instanceof FallThroughOp) {
+//                FallThroughOp fallThrough = (FallThroughOp) lastOp;
+//                if (fallThrough.fallThroughTarget() != null && lastOp.info == null) {
+//                    if (fallThrough.fallThroughTarget().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel()) {
+//                        fallThrough.setFallThroughTarget(null);
+//                    }
+//                }
+//            }
         }
 
         assert verify(code);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/EdgeMoveOptimizer.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/EdgeMoveOptimizer.java	Tue Jul 03 11:16:56 2012 +0200
@@ -33,7 +33,7 @@
  *
  * When a block has more than one predecessor, and all predecessors end with
  * the {@linkplain #same(LIRInstruction, LIRInstruction) same} sequence of
- * {@linkplain LIROpcode#Move move} instructions, then these sequences
+ * {@linkplain MoveOp move} instructions, then these sequences
  * can be replaced with a single copy of the sequence at the beginning of the block.
  *
  * Similarly, when a block has more than one successor, then same sequences of
@@ -78,9 +78,8 @@
     }
 
     /**
-     * Determines if two operations are both {@linkplain LIROpcode#Move moves}
-     * that have the same {@linkplain LIRInstruction#operand() source} and {@linkplain LIRInstruction#result() destination}
-     * operands and they have the same {@linkplain LIRInstruction#info debug info}.
+     * Determines if two operations are both {@linkplain MoveOp moves}
+     * that have the same {@linkplain MoveOp#getInput() source} and {@linkplain MoveOp#getResult() destination} operands.
      *
      * @param op1 the first instruction to compare
      * @param op2 the second instruction to compare
@@ -138,7 +137,7 @@
             assert pred.suxAt(0) == block : "invalid control flow";
             assert predInstructions.get(predInstructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump";
 
-            if (predInstructions.get(predInstructions.size() - 1).info != null) {
+            if (predInstructions.get(predInstructions.size() - 1).hasState()) {
                 // can not optimize instructions that have debug info
                 return;
             }
@@ -195,13 +194,13 @@
 
         assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump";
 
-        if (instructions.get(instructions.size() - 1).info != null) {
+        if (instructions.get(instructions.size() - 1).hasState()) {
             // cannot optimize instructions when debug info is needed
             return;
         }
 
         LIRInstruction branch = instructions.get(instructions.size() - 2);
-        if (!(branch instanceof StandardOp.BranchOp) || branch.info != null) {
+        if (!(branch instanceof StandardOp.BranchOp) || branch.hasState()) {
             // not a valid case for optimization
             // currently, only blocks that end with two branches (conditional branch followed
             // by unconditional branch) are optimized
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Tue Jul 03 11:16:56 2012 +0200
@@ -89,7 +89,7 @@
          * Sets the list for a specified binding.
          *
          * @param binding specifies the list to be replaced
-         * @param a list of intervals whose binding is {@code binding}
+         * @param list a list of intervals whose binding is {@code binding}
          */
         public void set(RegisterBinding binding, Interval list) {
             assert list != null;
@@ -155,7 +155,7 @@
          * Removes an interval from a list.
          *
          * @param binding specifies the list to be updated
-         * @param interval the interval to remove
+         * @param i the interval to remove
          */
         public void remove(RegisterBinding binding, Interval i) {
             Interval list = get(binding);
@@ -405,7 +405,7 @@
     public final Value operand;
 
     /**
-     * The {@linkplain OperandPool#operandNumber(Value) operand number} for this interval's {@linkplain #operand operand}.
+     * The operand number for this interval's {@linkplain #operand operand}.
      */
     public final int operandNumber;
 
@@ -421,7 +421,6 @@
 
     /**
      * The kind of this interval.
-     * Only valid if this is a {@linkplain #xxisVariable() variable}.
      */
     private Kind kind;
 
@@ -760,7 +759,7 @@
             int len = splitChildren.size();
 
             // in outputMode, the end of the interval (opId == cur.to()) is not valid
-            int toOffset = (mode == LIRInstruction.OperandMode.Output ? 0 : 1);
+            int toOffset = (mode == LIRInstruction.OperandMode.DEF ? 0 : 1);
 
             int i;
             for (i = 0; i < len; i++) {
@@ -906,7 +905,7 @@
     }
 
     void addUsePos(int pos, RegisterPriority registerPriority) {
-        assert covers(pos, LIRInstruction.OperandMode.Input) : "use position not covered by live range";
+        assert covers(pos, LIRInstruction.OperandMode.USE) : "use position not covered by live range";
 
         // do not add use positions for precolored intervals because they are never used
         if (registerPriority != RegisterPriority.None && isVariable(operand)) {
@@ -1064,7 +1063,7 @@
         if (cur != Range.EndMarker) {
             assert cur.to != cur.next.from : "ranges not separated";
 
-            if (mode == LIRInstruction.OperandMode.Output) {
+            if (mode == LIRInstruction.OperandMode.DEF) {
                 return cur.from <= opId && opId < cur.to;
             } else {
                 return cur.from <= opId && opId <= cur.to;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.compiler.alloc;
 
-import static com.oracle.graal.alloc.util.LocationUtil.*;
 import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRValueUtil.*;
+
 import java.util.*;
 
-import com.oracle.max.criutils.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
@@ -38,9 +39,13 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.StateProcedure;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.cfg.*;
+import com.oracle.max.criutils.*;
 
 /**
  * An implementation of the linear scan register allocator algorithm described
@@ -61,31 +66,31 @@
 
     public static class BlockData {
         /**
-         * Bit map specifying which {@linkplain OperandPool operands} are live upon entry to this block.
+         * Bit map specifying which operands are live upon entry to this block.
          * These are values used in this block or any of its successors where such value are not defined
          * in this block.
-         * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.oracle.max.cri.Value.RiValue.ci.CiValue) operand number}.
+         * The bit index of an operand is its {@linkplain LinearScan#operandNumber(Value) operand number}.
          */
         public BitSet liveIn;
 
         /**
-         * Bit map specifying which {@linkplain OperandPool operands} are live upon exit from this block.
+         * Bit map specifying which operands are live upon exit from this block.
          * These are values used in a successor block that are either defined in this block or were live
          * upon entry to this block.
-         * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.oracle.max.cri.Value.RiValue.ci.CiValue) operand number}.
+         * The bit index of an operand is its {@linkplain LinearScan#operandNumber(Value) operand number}.
          */
         public BitSet liveOut;
 
         /**
-         * Bit map specifying which {@linkplain OperandPool operands} are used (before being defined) in this block.
+         * Bit map specifying which operands are used (before being defined) in this block.
          * That is, these are the values that are live upon entry to the block.
-         * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.oracle.max.cri.Value.RiValue.ci.CiValue) operand number}.
+         * The bit index of an operand is its {@linkplain LinearScan#operandNumber(Value) operand number}.
          */
         public BitSet liveGen;
 
         /**
-         * Bit map specifying which {@linkplain OperandPool operands} are defined/overwritten in this block.
-         * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.oracle.max.cri.Value.RiValue.ci.CiValue) operand number}.
+         * Bit map specifying which operands are defined/overwritten in this block.
+         * The bit index of an operand is its {@linkplain LinearScan#operandNumber(Value) operand number}.
          */
         public BitSet liveKill;
     }
@@ -144,8 +149,7 @@
     private final ArrayList<Variable> variables;
 
     /**
-     * The {@linkplain #operandNumber(Value) number} of the first variable operand
-     * {@linkplain #newVariable(Kind) allocated} from this pool.
+     * The {@linkplain #operandNumber(Value) number} of the first variable operand allocated.
      */
     private final int firstVariableNumber;
 
@@ -306,7 +310,7 @@
     }
 
     /**
-     * Gets the size of the {@link Block#liveIn} and {@link Block#liveOut} sets for a basic block. These sets do
+     * Gets the size of the {@link BlockData#liveIn} and {@link BlockData#liveOut} sets for a basic block. These sets do
      * not include any operands allocated as a result of creating {@linkplain #createDerivedInterval(Interval) derived
      * intervals}.
      */
@@ -640,7 +644,7 @@
     }
 
     /**
-     * Computes local live sets (i.e. {@link Block#liveGen} and {@link Block#liveKill}) separately for each block.
+     * Computes local live sets (i.e. {@link BlockData#liveGen} and {@link BlockData#liveKill}) separately for each block.
      */
     void computeLocalLiveSets() {
         int numBlocks = blockCount();
@@ -763,8 +767,8 @@
     }
 
     /**
-     * Performs a backward dataflow analysis to compute global live sets (i.e. {@link Block#liveIn} and
-     * {@link Block#liveOut}) for each block.
+     * Performs a backward dataflow analysis to compute global live sets (i.e. {@link BlockData#liveIn} and
+     * {@link BlockData#liveOut}) for each block.
      */
     void computeGlobalLiveSets() {
         int numBlocks = blockCount();
@@ -868,16 +872,13 @@
                         TTY.println("  used in block B%d", block.getId());
                         for (LIRInstruction ins : block.lir) {
                             TTY.println(ins.id() + ": " + ins.toString());
-                            LIRDebugInfo info = ins.info;
-                            if (info != null) {
-                                info.forEachState(new ValueProcedure() {
-                                    @Override
-                                    public Value doValue(Value liveStateOperand) {
-                                        TTY.println("   operand=" + liveStateOperand);
-                                        return liveStateOperand;
-                                    }
-                                });
-                            }
+                            ins.forEachState(new ValueProcedure() {
+                                @Override
+                                public Value doValue(Value liveStateOperand) {
+                                    TTY.println("   operand=" + liveStateOperand);
+                                    return liveStateOperand;
+                                }
+                            });
                         }
                     }
                     if (blockData.get(block).liveKill.get(operandNum)) {
@@ -1033,7 +1034,7 @@
      * Determines the priority which with an instruction's input operand will be allocated a register.
      */
     static RegisterPriority registerPriorityOfInputOperand(EnumSet<OperandFlag> flags) {
-        if (flags.contains(OperandFlag.Stack)) {
+        if (flags.contains(OperandFlag.STACK)) {
             return RegisterPriority.ShouldHaveRegister;
         }
         // all other operands require a register
@@ -1069,7 +1070,7 @@
     }
 
     void addRegisterHint(final LIRInstruction op, final Value targetValue, OperandMode mode, EnumSet<OperandFlag> flags) {
-        if (flags.contains(OperandFlag.RegisterHint) && isVariableOrRegister(targetValue)) {
+        if (flags.contains(OperandFlag.HINT) && isVariableOrRegister(targetValue)) {
 
             op.forEachRegisterHint(targetValue, mode, new ValueProcedure() {
                 @Override
@@ -1402,21 +1403,21 @@
         assert isVariable(operand) : "register number out of bounds";
         assert intervalFor(operand) != null : "no interval found";
 
-        return splitChildAtOpId(intervalFor(operand), block.getFirstLirInstructionId(), LIRInstruction.OperandMode.Output);
+        return splitChildAtOpId(intervalFor(operand), block.getFirstLirInstructionId(), LIRInstruction.OperandMode.DEF);
     }
 
     Interval intervalAtBlockEnd(Block block, Value operand) {
         assert isVariable(operand) : "register number out of bounds";
         assert intervalFor(operand) != null : "no interval found";
 
-        return splitChildAtOpId(intervalFor(operand), block.getLastLirInstructionId() + 1, LIRInstruction.OperandMode.Output);
+        return splitChildAtOpId(intervalFor(operand), block.getLastLirInstructionId() + 1, LIRInstruction.OperandMode.DEF);
     }
 
     Interval intervalAtOpId(Value operand, int opId) {
         assert isVariable(operand) : "register number out of bounds";
         assert intervalFor(operand) != null : "no interval found";
 
-        return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.Input);
+        return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.USE);
     }
 
     void resolveCollectMappings(Block fromBlock, Block toBlock, MoveResolver moveResolver) {
@@ -1698,20 +1699,7 @@
     }
 
 
-    private void computeDebugInfo(IntervalWalker iw, LIRInstruction op) {
-        assert iw != null : "interval walker needed for debug information";
-        computeDebugInfo(iw, op, op.info);
-
-        if (op instanceof LIRXirInstruction) {
-            LIRXirInstruction xir = (LIRXirInstruction) op;
-            if (xir.infoAfter != null) {
-                computeDebugInfo(iw, op, xir.infoAfter);
-            }
-        }
-    }
-
-
-    private void computeDebugInfo(IntervalWalker iw, final LIRInstruction op, LIRDebugInfo info) {
+    private void computeDebugInfo(IntervalWalker iw, final LIRInstruction op, LIRFrameState info) {
         BitSet registerRefMap = op.hasCall() ? null : frameMap.initRegisterRefMap();
         BitSet frameRefMap = frameMap.initFrameRefMap();
         computeOopMap(iw, op, registerRefMap, frameRefMap);
@@ -1720,7 +1708,7 @@
             @Override
             public Value doValue(Value operand) {
                 int tempOpId = op.id();
-                OperandMode mode = OperandMode.Input;
+                OperandMode mode = OperandMode.USE;
                 Block block = blockForId(tempOpId);
                 if (block.numberOfSux() == 1 && tempOpId == block.getLastLirInstructionId()) {
                     // generating debug information for the last instruction of a block.
@@ -1732,7 +1720,7 @@
                     if (instr instanceof StandardOp.JumpOp) {
                         if (blockData.get(block).liveOut.get(operandNumber(operand))) {
                             tempOpId = block.suxAt(0).getFirstLirInstructionId();
-                            mode = OperandMode.Output;
+                            mode = OperandMode.DEF;
                         }
                     }
                 }
@@ -1749,7 +1737,7 @@
         info.finish(registerRefMap, frameRefMap, frameMap);
     }
 
-    private void assignLocations(List<LIRInstruction> instructions, IntervalWalker iw) {
+    private void assignLocations(List<LIRInstruction> instructions, final IntervalWalker iw) {
         int numInst = instructions.size();
         boolean hasDead = false;
 
@@ -1775,10 +1763,13 @@
             op.forEachTemp(assignProc);
             op.forEachOutput(assignProc);
 
-            if (op.info != null) {
-                // compute reference map and debug information
-                computeDebugInfo(iw, op);
-            }
+            // compute reference map and debug information
+            op.forEachState(new StateProcedure() {
+                @Override
+                protected void doState(LIRFrameState state) {
+                    computeDebugInfo(iw, op, state);
+                }
+            });
 
             // remove useless moves
             if (op instanceof MoveOp) {
@@ -2050,7 +2041,7 @@
             for (int j = 0; j < instructions.size(); j++) {
                 LIRInstruction op = instructions.get(j);
 
-                if (op.info != null) {
+                if (op.hasState()) {
                     iw.walkBefore(op.id());
                     boolean checkLive = true;
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Tue Jul 03 11:16:56 2012 +0200
@@ -867,8 +867,8 @@
             return;
         }
 
-        Interval beginHint = registerHint.getSplitChildAtOpId(beginPos, LIRInstruction.OperandMode.Input, allocator);
-        Interval endHint = registerHint.getSplitChildAtOpId(endPos, LIRInstruction.OperandMode.Output, allocator);
+        Interval beginHint = registerHint.getSplitChildAtOpId(beginPos, LIRInstruction.OperandMode.USE, allocator);
+        Interval endHint = registerHint.getSplitChildAtOpId(endPos, LIRInstruction.OperandMode.DEF, allocator);
         if (beginHint == endHint || beginHint.to() != beginPos || endHint.from() != endPos) {
             // registerHint must be split : otherwise the re-writing of use positions does not work
             return;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Tue Jul 03 11:16:56 2012 +0200
@@ -44,7 +44,7 @@
 
     private HashMap<VirtualObjectNode, VirtualObject> virtualObjects = new HashMap<>();
 
-    public LIRDebugInfo build(FrameState topState, LockScope locks, List<StackSlot> pointerSlots, LabelRef exceptionEdge, long leafGraphId) {
+    public LIRFrameState build(FrameState topState, LockScope locks, List<StackSlot> pointerSlots, LabelRef exceptionEdge, long leafGraphId) {
         assert virtualObjects.size() == 0;
         BytecodeFrame frame = computeFrameForState(topState, locks, leafGraphId);
 
@@ -94,7 +94,7 @@
             virtualObjects.clear();
         }
 
-        return new LIRDebugInfo(frame, virtualObjectsArray, pointerSlots, exceptionEdge);
+        return new LIRFrameState(frame, virtualObjectsArray, pointerSlots, exceptionEdge);
     }
 
     private BytecodeFrame computeFrameForState(FrameState state, LockScope locks, long leafGraphId) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/InstructionPrinter.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/InstructionPrinter.java	Tue Jul 03 11:16:56 2012 +0200
@@ -28,12 +28,11 @@
 import com.oracle.graal.nodes.*;
 
 /**
- * A {@link ValueVisitor} for {@linkplain #printInstruction(ValueNode) printing}
- * an {@link FixedWithNextNode} as an expression or statement.
+ * A utility for {@linkplain #printInstruction(ValueNode) printing}
+ * a node as an expression or statement.
  */
 public class InstructionPrinter {
 
-
     /**
      * The columns printed in a tabulated instruction
      * {@linkplain InstructionPrinter#printInstructionListing(ValueNode) listing}.
@@ -50,7 +49,7 @@
         USE(7, "use"),
 
         /**
-         * The instruction as a {@linkplain com.oracle.graal.compiler.util.Util#valueString(com.oracle.graal.compiler.ir.Value) value}.
+         * The instruction as a value.
          */
         VALUE(12, "tid"),
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Jul 03 11:16:56 2012 +0200
@@ -163,7 +163,7 @@
     }
 
     /**
-     * Returns the operand that has been previously initialized by {@link #setResult()}
+     * Returns the operand that has been previously initialized by {@link #setResult(ValueNode, Value)}
      * with the result of an instruction.
      * @param node A node that produces a result value.
      */
@@ -261,21 +261,21 @@
         return LabelRef.forSuccessor(currentBlock, suxIndex);
     }
 
-    public LIRDebugInfo state() {
+    public LIRFrameState state() {
         assert lastState != null : "must have state before instruction";
         return stateFor(lastState, -1);
     }
 
-    public LIRDebugInfo state(long leafGraphId) {
+    public LIRFrameState state(long leafGraphId) {
         assert lastState != null : "must have state before instruction";
         return stateFor(lastState, leafGraphId);
     }
 
-    public LIRDebugInfo stateFor(FrameState state, long leafGraphId) {
+    public LIRFrameState stateFor(FrameState state, long leafGraphId) {
         return stateFor(state, null, null, leafGraphId);
     }
 
-    public LIRDebugInfo stateFor(FrameState state, List<StackSlot> pointerSlots, LabelRef exceptionEdge, long leafGraphId) {
+    public LIRFrameState stateFor(FrameState state, List<StackSlot> pointerSlots, LabelRef exceptionEdge, long leafGraphId) {
         return debugInfoBuilder.build(state, curLocks, pointerSlots, exceptionEdge, leafGraphId);
     }
 
@@ -509,7 +509,7 @@
     }
 
     protected void emitPrologue() {
-        CallingConvention incomingArguments = frameMap.registerConfig.getCallingConvention(JavaCallee, CodeUtil.signatureToKinds(method), target, false);
+        CallingConvention incomingArguments = frameMap.registerConfig.getCallingConvention(JavaCallee, MetaUtil.signatureToKinds(method), target, false);
 
         Value[] params = new Value[incomingArguments.locations.length];
         for (int i = 0; i < params.length; i++) {
@@ -552,11 +552,11 @@
         XirArgument obj = toXirArgument(x.object());
         XirArgument lockAddress = lockData == null ? null : toXirArgument(emitLea(lockData));
 
-        LIRDebugInfo stateBefore = state();
+        LIRFrameState stateBefore = state();
         // The state before the monitor enter is used for null checks, so it must not contain the newly locked object.
         curLocks = new LockScope(curLocks, x.stateAfter().inliningIdentifier(), x, lockData);
         // The state after the monitor enter is used for deoptimization, after the monitor has blocked, so it must contain the newly locked object.
-        LIRDebugInfo stateAfter = stateFor(x.stateAfter(), -1);
+        LIRFrameState stateAfter = stateFor(x.stateAfter(), -1);
 
         XirSnippet snippet = xir.genMonitorEnter(site(x, x.object()), obj, lockAddress);
         emitXir(snippet, x, stateBefore, stateAfter, true, null, null);
@@ -576,7 +576,7 @@
         XirArgument obj = toXirArgument(x.object());
         XirArgument lockAddress = lockData == null ? null : toXirArgument(emitLea(lockData));
 
-        LIRDebugInfo stateBefore = state();
+        LIRFrameState stateBefore = state();
         curLocks = curLocks.outer;
 
         XirSnippet snippet = xir.genMonitorExit(site(x, x.object()), obj, lockAddress);
@@ -686,7 +686,6 @@
 
     @Override
     public void emitIf(IfNode x) {
-        assert x.defaultSuccessor() == x.falseSuccessor() : "wrong destination";
         emitBranch(x.compare(), getLIRBlock(x.trueSuccessor()),  getLIRBlock(x.falseSuccessor()), null);
     }
 
@@ -699,7 +698,7 @@
             // False constants are handled within emitBranch.
         } else {
             // Fall back to a normal branch.
-            LIRDebugInfo info = state(leafGraphId);
+            LIRFrameState info = state(leafGraphId);
             LabelRef stubEntry = createDeoptStub(action, deoptReason, info, comp);
             if (negated) {
                 emitBranch(comp, stubEntry, null, info);
@@ -711,7 +710,7 @@
 
     protected abstract void emitNullCheckGuard(ValueNode object, long leafGraphId);
 
-    public void emitBranch(BooleanNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) {
+    public void emitBranch(BooleanNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
         if (node instanceof IsNullNode) {
             emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, info);
         } else if (node instanceof CompareNode) {
@@ -727,7 +726,7 @@
         }
     }
 
-    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) {
+    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
         if (falseSuccessor != null) {
             emitBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor, info);
             if (trueSuccessor != null) {
@@ -738,7 +737,7 @@
         }
     }
 
-    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRDebugInfo info) {
+    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
         if (falseSuccessorBlock != null) {
             emitBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock, info);
             if (trueSuccessorBlock != null) {
@@ -749,20 +748,20 @@
         }
     }
 
-    private void emitInstanceOfBranch(InstanceOfNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) {
+    private void emitInstanceOfBranch(InstanceOfNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
         XirArgument obj = toXirArgument(x.object());
         XirSnippet snippet = xir.genInstanceOf(site(x, x.object()), obj, toXirArgument(x.targetClassInstruction()), x.targetClass(), x.profile());
         emitXir(snippet, x, info, null, false, trueSuccessor, falseSuccessor);
     }
 
-    public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRDebugInfo info) {
+    public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
         LabelRef block = value ? trueSuccessorBlock : falseSuccessorBlock;
         if (block != null) {
             emitJump(block, info);
         }
     }
 
-    public void emitTypeBranch(IsTypeNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) {
+    public void emitTypeBranch(IsTypeNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
         XirArgument thisClass = toXirArgument(x.objectClass());
         XirArgument otherClass = toXirArgument(x.type().getEncoding(Representation.ObjectHub));
         XirSnippet snippet = xir.genTypeBranch(site(x), thisClass, otherClass, x.type());
@@ -815,8 +814,8 @@
 
 
     public abstract void emitLabel(Label label, boolean align);
-    public abstract void emitJump(LabelRef label, LIRDebugInfo info);
-    public abstract void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRDebugInfo info);
+    public abstract void emitJump(LabelRef label, LIRFrameState info);
+    public abstract void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info);
     public abstract Variable emitCMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
 
     protected FrameState stateBeforeCallWithArguments(FrameState stateAfter, MethodCallTargetNode call, int bci) {
@@ -883,24 +882,24 @@
         if (!target().invokeSnippetAfterArguments) {
             // This is the version currently necessary for Maxine: since the invokeinterface-snippet uses a division, it
             // destroys rdx, which is also used to pass a parameter.  Therefore, the snippet must be before the parameters are assigned to their locations.
-            LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), x.leafGraphId());
+            LIRFrameState addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), x.leafGraphId());
             destinationAddress = emitXir(snippet, x.node(), addrInfo, false);
         }
 
         Value resultOperand = resultOperandFor(x.node().kind());
 
-        Kind[] signature = CodeUtil.signatureToKinds(callTarget.targetMethod().signature(), callTarget.isStatic() ? null : callTarget.targetMethod().holder().kind());
+        Kind[] signature = MetaUtil.signatureToKinds(callTarget.targetMethod().signature(), callTarget.isStatic() ? null : callTarget.targetMethod().holder().kind());
         CallingConvention cc = frameMap.registerConfig.getCallingConvention(JavaCall, signature, target(), false);
         frameMap.callsMethod(cc, JavaCall);
         List<Value> argList = visitInvokeArguments(cc, callTarget.arguments());
 
         if (target().invokeSnippetAfterArguments) {
             // This is the version currently active for HotSpot.
-            LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), null, null, x.leafGraphId());
+            LIRFrameState addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), null, null, x.leafGraphId());
             destinationAddress = emitXir(snippet, x.node(), addrInfo, false);
         }
 
-        LIRDebugInfo callInfo = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null, x.leafGraphId());
+        LIRFrameState callInfo = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null, x.leafGraphId());
         emitCall(targetMethod, resultOperand, argList, destinationAddress, callInfo, snippet.marks);
 
         if (isLegal(resultOperand)) {
@@ -908,7 +907,7 @@
         }
     }
 
-    protected abstract void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRDebugInfo info, Map<XirMark, Mark> marks);
+    protected abstract void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRFrameState info, Map<XirMark, Mark> marks);
 
 
     private static Value toStackKind(Value value) {
@@ -943,11 +942,11 @@
     }
 
 
-    protected abstract LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRDebugInfo info, Object deoptInfo);
+    protected abstract LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo);
 
     @Override
     public Variable emitCall(@SuppressWarnings("hiding") Object target, Kind result, Kind[] arguments, boolean canTrap, Value... args) {
-        LIRDebugInfo info = canTrap ? state() : null;
+        LIRFrameState info = canTrap ? state() : null;
 
         Value physReg = resultOperandFor(result);
 
@@ -985,7 +984,7 @@
         frameMap.callsMethod(cc, RuntimeCall);
         List<Value> argList = visitInvokeArguments(cc, x.arguments());
 
-        LIRDebugInfo info = null;
+        LIRFrameState info = null;
         FrameState stateAfter = x.stateAfter();
         if (stateAfter != null) {
             // (cwimmer) I made the code that modifies the operand stack conditional. My scenario: runtime calls to, e.g.,
@@ -1014,128 +1013,138 @@
         }
     }
 
+    /**
+     * This method tries to create a switch implementation that is optimal for the given switch.
+     * It will either generate a sequential if/then/else cascade, a set of range tests or a table switch.
+     *
+     * If the given switch does not contain int keys, it will always create a sequential implementation.
+     */
     @Override
-    public void emitLookupSwitch(LookupSwitchNode x) {
-        Variable tag = load(operand(x.value()));
-        if (x.numberOfCases() == 0 || x.numberOfCases() < GraalOptions.SequentialSwitchLimit) {
-            int len = x.numberOfCases();
-            for (int i = 0; i < len; i++) {
-                emitBranch(tag, Constant.forInt(x.keyAt(i)), Condition.EQ, false, getLIRBlock(x.blockSuccessor(i)), null);
-            }
+    public void emitSwitch(SwitchNode x) {
+        int keyCount = x.keyCount();
+        if (keyCount == 0) {
             emitJump(getLIRBlock(x.defaultSuccessor()), null);
         } else {
-            visitSwitchRanges(createSwitchRanges(x, null), tag, getLIRBlock(x.defaultSuccessor()));
-        }
-    }
-
-    @Override
-    public void emitTypeSwitch(TypeSwitchNode x) {
-        Variable tag = load(operand(x.value()));
-        int len = x.numberOfCases();
-        for (int i = 0; i < len; i++) {
-            ResolvedJavaType type = x.keyAt(i);
-            emitBranch(tag, type.getEncoding(Representation.ObjectHub), Condition.EQ, false, getLIRBlock(x.blockSuccessor(i)), null);
-        }
-        emitJump(getLIRBlock(x.defaultSuccessor()), null);
-    }
-
-    @Override
-    public void emitTableSwitch(TableSwitchNode x) {
-        Variable value = load(operand(x.value()));
-        // TODO: tune the defaults for the controls used to determine what kind of translation to use
-        if (x.numberOfCases() == 0 || x.numberOfCases() <= GraalOptions.SequentialSwitchLimit) {
-            int loKey = x.lowKey();
-            int len = x.numberOfCases();
-            for (int i = 0; i < len; i++) {
-                emitBranch(value, Constant.forInt(i + loKey), Condition.EQ, false, getLIRBlock(x.blockSuccessor(i)), null);
-            }
-            emitJump(getLIRBlock(x.defaultSuccessor()), null);
-        } else {
-            SwitchRange[] switchRanges = createSwitchRanges(null, x);
-            int rangeDensity = x.numberOfCases() / switchRanges.length;
-            if (rangeDensity >= GraalOptions.RangeTestsSwitchDensity) {
-                visitSwitchRanges(switchRanges, value, getLIRBlock(x.defaultSuccessor()));
+            Variable value = load(operand(x.value()));
+            LabelRef defaultTarget = x.defaultSuccessor() == null ? null : getLIRBlock(x.defaultSuccessor());
+            if (value.kind == Kind.Object || keyCount < GraalOptions.SequentialSwitchLimit) {
+                // only a few entries
+                emitSequentialSwitch(x, value, defaultTarget);
             } else {
-                LabelRef[] targets = new LabelRef[x.numberOfCases()];
-                for (int i = 0; i < x.numberOfCases(); ++i) {
-                    targets[i] = getLIRBlock(x.blockSuccessor(i));
+                long valueRange = x.keyAt(keyCount - 1).asLong() - x.keyAt(0).asLong() + 1;
+                int switchRangeCount = switchRangeCount(x);
+                int rangeDensity = keyCount / switchRangeCount;
+                if (rangeDensity >= GraalOptions.RangeTestsSwitchDensity) {
+                    emitSwitchRanges(x, switchRangeCount, value, defaultTarget);
+                } else if (keyCount / (double) valueRange >= GraalOptions.MinTableSwitchDensity) {
+                    int minValue = x.keyAt(0).asInt();
+                    assert valueRange < Integer.MAX_VALUE;
+                    LabelRef[] targets = new LabelRef[(int) valueRange];
+                    for (int i = 0; i < valueRange; i++) {
+                        targets[i] = defaultTarget;
+                    }
+                    for (int i = 0; i < keyCount; i++) {
+                        targets[x.keyAt(i).asInt() - minValue] = getLIRBlock(x.keySuccessor(i));
+                    }
+                    emitTableSwitch(minValue, defaultTarget, targets, value);
+                } else {
+                    emitSequentialSwitch(x, value, defaultTarget);
                 }
-                emitTableSwitch(x.lowKey(), getLIRBlock(x.defaultSuccessor()), targets, value);
             }
         }
     }
 
-    protected abstract void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value index);
+    private void emitSequentialSwitch(final SwitchNode x, Variable key, LabelRef defaultTarget) {
+        int keyCount = x.keyCount();
+        Integer[] indexes = new Integer[keyCount];
+        for (int i = 0; i < keyCount; i++) {
+            indexes[i] = i;
+        }
+        Arrays.sort(indexes, new Comparator<Integer>() {
+            @Override
+            public int compare(Integer o1, Integer o2) {
+                return x.keyProbability(o1) < x.keyProbability(o2) ? 1 : x.keyProbability(o1) > x.keyProbability(o2) ? -1 : 0;
+            }
+        });
+        LabelRef[] keyTargets = new LabelRef[keyCount];
+        Constant[] keyConstants = new Constant[keyCount];
+        for (int i = 0; i < keyCount; i++) {
+            keyTargets[i] = getLIRBlock(x.keySuccessor(indexes[i]));
+            keyConstants[i] = x.keyAt(indexes[i]);
+        }
+        emitSequentialSwitch(keyConstants, keyTargets, defaultTarget, key);
+    }
 
-    // the range of values in a lookupswitch or tableswitch statement
-    private static final class SwitchRange {
-        protected final int lowKey;
-        protected int highKey;
-        protected final LabelRef sux;
+    protected abstract void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key);
+    protected abstract void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key);
+    protected abstract void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key);
 
-        SwitchRange(int lowKey, LabelRef sux) {
-            this.lowKey = lowKey;
-            this.highKey = lowKey;
-            this.sux = sux;
+    private static int switchRangeCount(SwitchNode x) {
+        int keyCount = x.keyCount();
+        int i = 0;
+        while (i < keyCount && x.keySuccessorIndex(i) == x.defaultSuccessorIndex()) {
+            i++;
+        }
+        if (i == keyCount) {
+            return 0;
+        } else {
+            int switchRangeCount = 1;
+            i++;
+            for (; i < keyCount; i++) {
+                if (x.keySuccessorIndex(i) != x.defaultSuccessorIndex()) {
+                    if (x.keyAt(i).asInt() != x.keyAt(i - 1).asInt() + 1 || x.keySuccessorIndex(i) != x.keySuccessorIndex(i - 1)) {
+                        switchRangeCount++;
+                    }
+                }
+            }
+            return switchRangeCount;
         }
     }
 
-    private SwitchRange[] createSwitchRanges(LookupSwitchNode ls, TableSwitchNode ts) {
-        // Only one of the parameters is used, but code is shared because it is mostly the same.
-        SwitchNode x = ls != null ? ls : ts;
-        // we expect the keys to be sorted by increasing value
-        List<SwitchRange> res = new ArrayList<>(x.numberOfCases());
-        int len = x.numberOfCases();
-        if (len > 0) {
-            LabelRef defaultSux = getLIRBlock(x.defaultSuccessor());
-            int key = ls != null ? ls.keyAt(0) : ts.lowKey();
-            LabelRef sux = getLIRBlock(x.blockSuccessor(0));
-            SwitchRange range = new SwitchRange(key, sux);
-            for (int i = 1; i < len; i++) {
-                int newKey = ls != null ? ls.keyAt(i) : key + 1;
-                LabelRef newSux = getLIRBlock(x.blockSuccessor(i));
-                if (key + 1 == newKey && sux == newSux) {
-                    // still in same range
-                    range.highKey = newKey;
-                } else {
-                    // skip tests which explicitly dispatch to the default
-                    if (range.sux != defaultSux) {
-                        res.add(range);
+    private void emitSwitchRanges(SwitchNode x, int switchRangeCount, Variable keyValue, LabelRef defaultTarget) {
+        int[] lowKeys = new int[switchRangeCount];
+        int[] highKeys = new int[switchRangeCount];
+        LabelRef[] targets = new LabelRef[switchRangeCount];
+
+        int keyCount = x.keyCount();
+        int defaultSuccessor = x.defaultSuccessorIndex();
+
+        int current = 0;
+        int i = 0;
+        while (i < keyCount && x.keySuccessorIndex(i) == x.defaultSuccessorIndex()) {
+            i++;
+        }
+        if (i == keyCount) {
+            emitJump(defaultTarget, null);
+        } else {
+            int key = x.keyAt(i).asInt();
+            int successor = x.keySuccessorIndex(i);
+            lowKeys[current] = key;
+            highKeys[current] = key;
+            targets[current] = getLIRBlock(x.blockSuccessor(successor));
+            i++;
+            for (; i < keyCount; i++) {
+                int newSuccessor = x.keySuccessorIndex(i);
+                if (newSuccessor != defaultSuccessor) {
+                    int newKey = x.keyAt(i).asInt();
+                    if (key + 1 == newKey && successor == newSuccessor) {
+                        // still in same range
+                        highKeys[current] = newKey;
+                    } else {
+                        current++;
+                        lowKeys[current] = newKey;
+                        highKeys[current] = newKey;
+                        targets[current] = getLIRBlock(x.blockSuccessor(newSuccessor));
                     }
-                    range = new SwitchRange(newKey, newSux);
+                    key = newKey;
                 }
-                key = newKey;
-                sux = newSux;
+                successor = newSuccessor;
             }
-            if (res.size() == 0 || res.get(res.size() - 1) != range) {
-                res.add(range);
-            }
+            assert current == switchRangeCount - 1;
+            emitSwitchRanges(lowKeys, highKeys, targets, defaultTarget, keyValue);
         }
-        return res.toArray(new SwitchRange[res.size()]);
     }
 
-    private void visitSwitchRanges(SwitchRange[] x, Variable value, LabelRef defaultSux) {
-        for (int i = 0; i < x.length; i++) {
-            SwitchRange oneRange = x[i];
-            int lowKey = oneRange.lowKey;
-            int highKey = oneRange.highKey;
-            LabelRef dest = oneRange.sux;
-            if (lowKey == highKey) {
-                emitBranch(value, Constant.forInt(lowKey), Condition.EQ, false, dest, null);
-            } else if (highKey - lowKey == 1) {
-                emitBranch(value, Constant.forInt(lowKey), Condition.EQ, false, dest, null);
-                emitBranch(value, Constant.forInt(highKey), Condition.EQ, false, dest, null);
-            } else {
-                Label l = new Label();
-                emitBranch(value, Constant.forInt(lowKey), Condition.LT, false, LabelRef.forLabel(l), null);
-                emitBranch(value, Constant.forInt(highKey), Condition.LE, false, dest, null);
-                emitLabel(l, false);
-            }
-        }
-        emitJump(defaultSux, null);
-    }
-
-
     protected XirArgument toXirArgument(Value v) {
         if (v == null) {
             return null;
@@ -1183,11 +1192,11 @@
         return variable;
     }
 
-    protected Value emitXir(XirSnippet snippet, ValueNode x, LIRDebugInfo info, boolean setInstructionResult) {
+    protected Value emitXir(XirSnippet snippet, ValueNode x, LIRFrameState info, boolean setInstructionResult) {
         return emitXir(snippet, x, info, null, setInstructionResult, null, null);
     }
 
-    protected Value emitXir(XirSnippet snippet, ValueNode instruction, LIRDebugInfo info, LIRDebugInfo infoAfter, boolean setInstructionResult, LabelRef trueSuccessor, LabelRef falseSuccessor) {
+    protected Value emitXir(XirSnippet snippet, ValueNode instruction, LIRFrameState info, LIRFrameState infoAfter, boolean setInstructionResult, LabelRef trueSuccessor, LabelRef falseSuccessor) {
         if (GraalOptions.PrintXirTemplates) {
             TTY.println("Emit XIR template " + snippet.template.name);
         }
@@ -1295,9 +1304,9 @@
     }
 
     protected abstract void emitXir(XirSnippet snippet, Value[] operands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex,
-                    LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor);
+                    LIRFrameState info, LIRFrameState infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor);
 
-    protected final Value callRuntime(RuntimeCall runtimeCall, LIRDebugInfo info, Value... args) {
+    protected final Value callRuntime(RuntimeCall runtimeCall, LIRFrameState info, Value... args) {
         // get a result register
         Kind result = runtimeCall.resultKind;
         Kind[] arguments = runtimeCall.arguments;
@@ -1327,73 +1336,11 @@
         return physReg;
     }
 
-    protected final Variable callRuntimeWithResult(RuntimeCall runtimeCall, LIRDebugInfo info, Value... args) {
+    protected final Variable callRuntimeWithResult(RuntimeCall runtimeCall, LIRFrameState info, Value... args) {
         Value location = callRuntime(runtimeCall, info, args);
         return emitMove(location);
     }
 
-    SwitchRange[] createLookupRanges(LookupSwitchNode x) {
-        // we expect the keys to be sorted by increasing value
-        List<SwitchRange> res = new ArrayList<>(x.numberOfCases());
-        int len = x.numberOfCases();
-        if (len > 0) {
-            LabelRef defaultSux = getLIRBlock(x.defaultSuccessor());
-            int key = x.keyAt(0);
-            LabelRef sux = getLIRBlock(x.blockSuccessor(0));
-            SwitchRange range = new SwitchRange(key, sux);
-            for (int i = 1; i < len; i++) {
-                int newKey = x.keyAt(i);
-                LabelRef newSux = getLIRBlock(x.blockSuccessor(i));
-                if (key + 1 == newKey && sux == newSux) {
-                    // still in same range
-                    range.highKey = newKey;
-                } else {
-                    // skip tests which explicitly dispatch to the default
-                    if (range.sux != defaultSux) {
-                        res.add(range);
-                    }
-                    range = new SwitchRange(newKey, newSux);
-                }
-                key = newKey;
-                sux = newSux;
-            }
-            if (res.size() == 0 || res.get(res.size() - 1) != range) {
-                res.add(range);
-            }
-        }
-        return res.toArray(new SwitchRange[res.size()]);
-    }
-
-    SwitchRange[] createLookupRanges(TableSwitchNode x) {
-        // TODO: try to merge this with the code for LookupSwitch
-        List<SwitchRange> res = new ArrayList<>(x.numberOfCases());
-        int len = x.numberOfCases();
-        if (len > 0) {
-            LabelRef sux = getLIRBlock(x.blockSuccessor(0));
-            int key = x.lowKey();
-            LabelRef defaultSux = getLIRBlock(x.defaultSuccessor());
-            SwitchRange range = new SwitchRange(key, sux);
-            for (int i = 0; i < len; i++, key++) {
-                LabelRef newSux = getLIRBlock(x.blockSuccessor(i));
-                if (sux == newSux) {
-                    // still in same range
-                    range.highKey = key;
-                } else {
-                    // skip tests which explicitly dispatch to the default
-                    if (sux != defaultSux) {
-                        res.add(range);
-                    }
-                    range = new SwitchRange(key, newSux);
-                }
-                sux = newSux;
-            }
-            if (res.size() == 0 || res.get(res.size() - 1) != range) {
-                res.add(range);
-            }
-        }
-        return res.toArray(new SwitchRange[res.size()]);
-    }
-
     protected XirSupport site(ValueNode x) {
         return xirSupport.site(x, null);
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopEx.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopEx.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,7 +22,8 @@
  */
 package com.oracle.graal.compiler.loop;
 
-import com.oracle.graal.api.code.*;
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
@@ -129,7 +130,7 @@
             }
             BinaryNode result = BinaryNode.reassociate(binary, invariant);
             if (result != binary) {
-                Debug.log(CodeUtil.format("%H::%n", Debug.contextLookup(ResolvedJavaMethod.class)) + " : Reassociated %s into %s", binary, result);
+                Debug.log(MetaUtil.format("%H::%n", Debug.contextLookup(ResolvedJavaMethod.class)) + " : Reassociated %s into %s", binary, result);
                 graph.replaceFloating(binary, result);
             }
         }
@@ -138,4 +139,30 @@
     public void setCounted(CountedLoopInfo countedLoopInfo) {
         counted = countedLoopInfo;
     }
+
+    public LoopsData loopsData() {
+        return data;
+    }
+
+    public NodeBitMap nodesInLoopFrom(BeginNode point, BeginNode until) {
+        Collection<BeginNode> blocks = new LinkedList<>();
+        Collection<BeginNode> exits = new LinkedList<>();
+        Queue<Block> work = new LinkedList<>();
+        ControlFlowGraph cfg = loopsData().controlFlowGraph();
+        work.add(cfg.blockFor(point));
+        Block untilBlock = until != null ? cfg.blockFor(until) : null;
+        while (!work.isEmpty()) {
+            Block b = work.remove();
+            if (b == untilBlock) {
+                continue;
+            }
+            if (lirLoop().exits.contains(b)) {
+                exits.add(b.getBeginNode());
+            } else if (lirLoop().blocks.contains(b)) {
+                blocks.add(b.getBeginNode());
+                work.addAll(b.getDominated());
+            }
+        }
+        return LoopFragment.computeNodes(point.graph(), blocks, exits);
+    }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java	Tue Jul 03 11:16:56 2012 +0200
@@ -30,6 +30,8 @@
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
+import com.oracle.graal.nodes.VirtualState.NodeClosure;
+import com.oracle.graal.nodes.VirtualState.VirtualClosure;
 
 
 public abstract class LoopFragment {
@@ -87,7 +89,13 @@
     public abstract NodeIterable<Node> nodes();
 
     public StructuredGraph graph() {
-        return (StructuredGraph) loop.loopBegin().graph();
+        LoopEx l;
+        if (isDuplicate()) {
+            l = original().loop();
+        } else {
+            l = loop();
+        }
+        return (StructuredGraph) l.loopBegin().graph();
     }
 
     protected abstract DuplicationReplacement getDuplicationReplacement();
@@ -97,11 +105,13 @@
     protected void patchNodes(final DuplicationReplacement dataFix) {
         if (isDuplicate() && !nodesReady) {
             assert !original.isDuplicate();
-            final DuplicationReplacement cfgFix = getDuplicationReplacement();
+            final DuplicationReplacement cfgFix = original().getDuplicationReplacement();
             DuplicationReplacement dr;
-            if (cfgFix == null) {
+            if (cfgFix == null && dataFix != null) {
                 dr = dataFix;
-            } else {
+            } else if (cfgFix != null && dataFix == null) {
+                dr = cfgFix;
+            } else if (cfgFix != null && dataFix != null) {
                 dr = new DuplicationReplacement() {
                     @Override
                     public Node replacement(Node o) {
@@ -117,8 +127,15 @@
                         return o;
                     }
                 };
+            } else {
+                dr = new DuplicationReplacement() {
+                    @Override
+                    public Node replacement(Node o) {
+                        return o;
+                    }
+                };
             }
-            duplicationMap = graph().addDuplicates(nodes(), dr);
+            duplicationMap = graph().addDuplicates(original().nodes(), dr);
             finishDuplication();
             nodesReady = true;
         } else {
@@ -126,20 +143,12 @@
         }
     }
 
-    public static Collection<BeginNode> toHirBlocks(Collection<Block> blocks) {
-        List<BeginNode> hir = new ArrayList<>(blocks.size());
-        for (Block b : blocks) {
-            hir.add(b.getBeginNode());
-        }
-        return hir;
-    }
-
     protected static NodeBitMap computeNodes(Graph graph, Collection<BeginNode> blocks) {
         return computeNodes(graph, blocks, Collections.<BeginNode>emptyList());
     }
 
     protected static NodeBitMap computeNodes(Graph graph, Collection<BeginNode> blocks, Collection<BeginNode> earlyExits) {
-        NodeBitMap nodes = graph.createNodeBitMap(true);
+        final NodeBitMap nodes = graph.createNodeBitMap(true);
         for (BeginNode b : blocks) {
             for (Node n : b.getBlockNodes()) {
                 if (n instanceof Invoke) {
@@ -158,6 +167,12 @@
             FrameState stateAfter = earlyExit.stateAfter();
             if (stateAfter != null) {
                 nodes.mark(stateAfter);
+                stateAfter.applyToVirtual(new VirtualClosure() {
+                    @Override
+                    public void apply(VirtualState node) {
+                        nodes.mark(node);
+                    }
+                });
             }
             nodes.mark(earlyExit);
             for (ValueProxyNode proxy : earlyExit.proxies()) {
@@ -205,19 +220,29 @@
         return false;
     }
 
+    public static Collection<BeginNode> toHirBlocks(Collection<Block> blocks) {
+        List<BeginNode> hir = new ArrayList<>(blocks.size());
+        for (Block b : blocks) {
+            hir.add(b.getBeginNode());
+        }
+        return hir;
+    }
+
     /**
      * Merges the early exits (i.e. loop exits) that were duplicated as part of this fragment, with the original fragment's exits.
      */
     protected void mergeEarlyExits() {
         assert isDuplicate();
         StructuredGraph graph = graph();
-        for (BeginNode earlyExit : toHirBlocks(original().loop().lirLoop().exits)) {
+        for (BeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().exits)) {
             FixedNode next = earlyExit.next();
-            if (earlyExit.isDeleted() || !this.contains(earlyExit)) {
+            if (earlyExit.isDeleted() || !this.original().contains(earlyExit)) {
                 continue;
             }
             BeginNode newEarlyExit = getDuplicatedNode(earlyExit);
-            assert newEarlyExit != null;
+            if (newEarlyExit == null) {
+                continue;
+            }
             MergeNode merge = graph.add(new MergeNode());
             merge.setProbability(next.probability());
             EndNode originalEnd = graph.add(new EndNode());
@@ -229,9 +254,10 @@
             merge.setNext(next);
 
             FrameState exitState = earlyExit.stateAfter();
+            FrameState newExitState = newEarlyExit.stateAfter();
             FrameState state = null;
             if (exitState != null) {
-                state = exitState.duplicate();
+                state = exitState.duplicateWithVirtualState();
                 merge.setStateAfter(state);
             }
 
@@ -239,8 +265,8 @@
                 anchored.replaceFirstInput(earlyExit, merge);
             }
 
-            for (ValueProxyNode vpn : earlyExit.proxies().snapshot()) {
-                ValueNode replaceWith;
+            for (final ValueProxyNode vpn : earlyExit.proxies().snapshot()) {
+                final ValueNode replaceWith;
                 ValueProxyNode newVpn = getDuplicatedNode(vpn);
                 if (newVpn != null) {
                     PhiNode phi = graph.add(vpn.type() == PhiType.Value ? new PhiNode(vpn.kind(), merge) : new PhiNode(vpn.type(), merge));
@@ -251,10 +277,23 @@
                     replaceWith = vpn.value();
                 }
                 if (state != null) {
-                    state.replaceFirstInput(vpn, replaceWith);
+                    state.applyToNonVirtual(new NodeClosure<ValueNode>() {
+                        @Override
+                        public void apply(Node from, ValueNode node) {
+                            if (node == vpn) {
+                                from.replaceFirstInput(vpn, replaceWith);
+                            }
+                        }
+                    });
                 }
                 for (Node usage : vpn.usages().snapshot()) {
-                    if (usage != exitState && !merge.isPhiAtMerge(usage)) {
+                    if (!merge.isPhiAtMerge(usage)) {
+                        if (usage instanceof VirtualState) {
+                            VirtualState stateUsage = (VirtualState) usage;
+                            if (exitState.isPartOfThisState(stateUsage) || newExitState.isPartOfThisState(stateUsage)) {
+                                continue;
+                            }
+                        }
                         usage.replaceFirstInput(vpn, replaceWith);
                     }
                 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java	Tue Jul 03 11:16:56 2012 +0200
@@ -41,7 +41,7 @@
      * In the unrolling case they will be used as the value that replace the loop-phis of the duplicated inside fragment
      */
     private Map<PhiNode, ValueNode> mergedInitializers;
-    private final DuplicationReplacement dataFix = new DuplicationReplacement() {
+    private final DuplicationReplacement dataFixBefore = new DuplicationReplacement() {
         @Override
         public Node replacement(Node oriInput) {
             if (!(oriInput instanceof ValueNode)) {
@@ -56,7 +56,7 @@
     }
 
     public LoopFragmentInside(LoopFragmentInside original) {
-        super(original.loop(), original);
+        super(null, original);
     }
 
     @Override
@@ -76,11 +76,16 @@
     }
 
     @Override
+    public LoopEx loop() {
+        assert !this.isDuplicate();
+        return super.loop();
+    }
+
+    @Override
     public void insertBefore(LoopEx loop) {
-        if (this.loop() != loop) {
-            throw new UnsupportedOperationException();
-        }
-        patchNodes(dataFix);
+        assert this.isDuplicate() && this.original().loop() == loop;
+
+        patchNodes(dataFixBefore);
 
         BeginNode end = mergeEnds();
 
@@ -88,7 +93,7 @@
 
         mergeEarlyExits();
 
-        BeginNode entry = getDuplicatedNode(this.loop().loopBegin());
+        BeginNode entry = getDuplicatedNode(loop.loopBegin());
         FrameState state = entry.stateAfter();
         if (state != null) {
             entry.setStateAfter(null);
@@ -137,7 +142,6 @@
     @Override
     protected void finishDuplication() {
         // TODO (gd) ?
-
     }
 
     private void patchPeeling(LoopFragmentInside peel) {
@@ -182,12 +186,13 @@
 
     /**
      * Gets the corresponding value in this fragment.
-     * @param peel the peel to look into
+     *
      * @param b original value
      * @return corresponding value in the peel
      */
     private ValueNode prim(ValueNode b) {
-        LoopBeginNode loopBegin = loop().loopBegin();
+        assert isDuplicate();
+        LoopBeginNode loopBegin = original().loop().loopBegin();
         if (loopBegin.isPhiAtMerge(b)) {
             PhiNode phi = (PhiNode) b;
             return phi.valueAt(loopBegin.forwardEnd());
@@ -203,9 +208,10 @@
     }
 
     private BeginNode mergeEnds() {
+        assert isDuplicate();
         List<EndNode> endsToMerge = new LinkedList<>();
         Map<EndNode, LoopEndNode> reverseEnds = new HashMap<>(); // map peel's exit to the corresponding loop exits
-        LoopBeginNode loopBegin = loop().loopBegin();
+        LoopBeginNode loopBegin = original().loop().loopBegin();
         for (LoopEndNode le : loopBegin.loopEnds()) {
             EndNode duplicate = getDuplicatedNode(le);
             if (duplicate != null) {
@@ -229,7 +235,7 @@
             FrameState state = loopBegin.stateAfter();
             FrameState duplicateState = null;
             if (state != null) {
-                duplicateState = state.duplicate();
+                duplicateState = state.duplicateWithVirtualState();
                 newExitMerge.setStateAfter(duplicateState);
             }
             for (EndNode end : endsToMerge) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentWhole.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentWhole.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.compiler.loop;
 
+import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.lir.cfg.*;
+import com.oracle.graal.nodes.*;
 
 
 public class LoopFragmentWhole extends LoopFragment {
@@ -34,10 +35,23 @@
         super(loop);
     }
 
+    public LoopFragmentWhole(LoopFragmentWhole original) {
+        super(null, original);
+    }
+
     @Override
     public LoopFragmentWhole duplicate() {
-        // TODO (gd) do not forget to make a FULL loop : do not forget the forward end which is not part of the original loop stricto sensus
-        return null;
+        LoopFragmentWhole loopFragmentWhole = new LoopFragmentWhole(this);
+        loopFragmentWhole.reify();
+        return loopFragmentWhole;
+    }
+
+    private void reify() {
+        assert this.isDuplicate();
+
+        patchNodes(null);
+
+        mergeEarlyExits();
     }
 
     @Override
@@ -51,13 +65,29 @@
 
     @Override
     protected DuplicationReplacement getDuplicationReplacement() {
-        return null;
+        final FixedNode entry = loop().entryPoint();
+        final Graph graph = this.graph();
+        return new DuplicationReplacement() {
+            @Override
+            public Node replacement(Node o) {
+                if (o == entry) {
+                    return graph.add(new EndNode());
+                }
+                return o;
+            }
+        };
+    }
+
+    public FixedNode entryPoint() {
+        if (isDuplicate()) {
+            return getDuplicatedNode(original().loop().loopBegin()).forwardEnd();
+        }
+        return loop().entryPoint();
     }
 
     @Override
     protected void finishDuplication() {
-        // TODO Auto-generated method stub
-
+        // TODO (gd) ?
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopPolicies.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopPolicies.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,6 +23,8 @@
 package com.oracle.graal.compiler.loop;
 
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
 
 
@@ -47,4 +49,24 @@
         int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count());
         return size * exactTrips <= maxNodes;
     }
+
+    public static boolean shouldTryUnswitch(@SuppressWarnings("unused") LoopEx loop) {
+        // TODO (gd) maybe there should be a may number of unswitching per loop
+        return true;
+    }
+
+    public static boolean shouldUnswitch(LoopEx loop, IfNode ifNode) {
+        Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(ifNode).getPostdominator();
+        BeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null;
+        int inTrueBranch = loop.nodesInLoopFrom(ifNode.trueSuccessor(), postDom).cardinality();
+        int inFalseBranch = loop.nodesInLoopFrom(ifNode.falseSuccessor(), postDom).cardinality();
+        int loopTotal = loop.size();
+        int netDiff = loopTotal - (inTrueBranch + inFalseBranch);
+        double uncertainty = (0.5 - Math.abs(ifNode.probability(IfNode.TRUE_EDGE) - 0.5)) * 2;
+        int maxDiff = GraalOptions.LoopUnswitchMaxIncrease + (int) (GraalOptions.LoopUnswitchUncertaintyBoost * loop.loopBegin().loopFrequency() * uncertainty);
+        Debug.log("shouldUnswitch(%s, %s) : delta=%d, max=%d, %.2f%% inside of if", loop, ifNode, netDiff, maxDiff, (double) (inTrueBranch + inFalseBranch) / loopTotal * 100);
+        return netDiff <= maxDiff;
+    }
+
+
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformations.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformations.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,13 +23,43 @@
 package com.oracle.graal.compiler.loop;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
 
 
 public abstract class LoopTransformations {
     private static final int UNROLL_LIMIT = GraalOptions.FullUnrollMaxNodes * 2;
+    private static final SimplifierTool simplifier = new SimplifierTool() {
+        @Override
+        public TargetDescription target() {
+            return null;
+        }
+        @Override
+        public CodeCacheProvider runtime() {
+            return null;
+        }
+        @Override
+        public boolean isImmutable(Constant objectConstant) {
+            return false;
+        }
+        @Override
+        public Assumptions assumptions() {
+            return null;
+        }
+        @Override
+        public void deleteBranch(FixedNode branch) {
+            branch.predecessor().replaceFirstSuccessor(branch, null);
+            GraphUtil.killCFG(branch);
+        }
+        @Override
+        public void addToWorkList(Node node) {
+        }
+    };
 
     private LoopTransformations() {
         // does not need to be instantiated
@@ -64,16 +94,19 @@
 
     public static void unswitch(LoopEx loop, IfNode ifNode) {
         // duplicate will be true case, original will be false case
-        LoopFragmentWhole duplicateLoop = loop.whole().duplicate();
+        LoopFragmentWhole originalLoop = loop.whole();
+        LoopFragmentWhole duplicateLoop = originalLoop.duplicate();
         StructuredGraph graph = (StructuredGraph) ifNode.graph();
         BeginNode tempBegin = graph.add(new BeginNode());
-        loop.entryPoint().replaceAtPredecessor(tempBegin);
+        originalLoop.entryPoint().replaceAtPredecessor(tempBegin);
         double takenProbability = ifNode.probability(ifNode.blockSuccessorIndex(ifNode.trueSuccessor()));
-        IfNode newIf = graph.add(new IfNode(ifNode.compare(), duplicateLoop.loop().entryPoint(), loop.entryPoint(), takenProbability));
+        IfNode newIf = graph.add(new IfNode(ifNode.compare(), duplicateLoop.entryPoint(), originalLoop.entryPoint(), takenProbability, ifNode.leafGraphId()));
         tempBegin.setNext(newIf);
         ifNode.setCompare(graph.unique(ConstantNode.forBoolean(false, graph)));
         IfNode duplicateIf = duplicateLoop.getDuplicatedNode(ifNode);
         duplicateIf.setCompare(graph.unique(ConstantNode.forBoolean(true, graph)));
+        ifNode.simplify(simplifier);
+        duplicateIf.simplify(simplifier);
         // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms)
     }
 
@@ -97,4 +130,13 @@
             inside.duplicate().appendInside(loop);
         }
     }
+
+    public static IfNode findUnswitchableIf(LoopEx loop) {
+        for (IfNode ifNode : loop.whole().nodes().filter(IfNode.class)) {
+            if (loop.isOutsideLoop(ifNode.compare())) {
+                return ifNode;
+            }
+        }
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopsData.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopsData.java	Tue Jul 03 11:16:56 2012 +0200
@@ -35,13 +35,14 @@
 public class LoopsData {
     private Map<Loop, LoopEx> lirLoopToEx = new IdentityHashMap<>();
     private Map<LoopBeginNode, LoopEx> loopBeginToEx = new IdentityHashMap<>();
+    private ControlFlowGraph cfg;
 
     public LoopsData(final StructuredGraph graph) {
 
-        ControlFlowGraph cfg = Debug.scope("ControlFlowGraph", new Callable<ControlFlowGraph>() {
+        cfg = Debug.scope("ControlFlowGraph", new Callable<ControlFlowGraph>() {
             @Override
             public ControlFlowGraph call() throws Exception {
-                return ControlFlowGraph.compute(graph, true, true, true, false);
+                return ControlFlowGraph.compute(graph, true, true, true, true);
             }
         });
         for (Loop lirLoop : cfg.getLoops()) {
@@ -150,4 +151,8 @@
             }
         }
     }
+
+    public ControlFlowGraph controlFlowGraph() {
+        return cfg;
+    }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/package-info.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/package-info.java	Tue Jul 03 11:16:56 2012 +0200
@@ -25,30 +25,6 @@
  * The top-level package in Graal containing options, metrics, timers and the main compiler class
  * {@link com.oracle.graal.compiler.GraalCompiler}.
  *
- * <H2>{@code GraalCompiler} Overview</H2>
- *
- * Graal is intended to be used with multiple JVM's so makes no use of or reference to classes for a specific JVM, for
- * example Maxine.
- *
- * The compiler is represented by the class {@code GraalCompiler}. {@code GraalCompiler} binds a specific target
- * architecture and JVM interface to produce a usable compiler object.
- * {@code RiMethod} is Graal's representation of a Java method and {@code RiXirGenerator} represents the interface through
- * which the compiler requests the XIR for a given bytecode from the runtime system.
- *
- * <H3>The Graal Compilation Process</H3>
- *
- * {@link com.oracle.graal.compiler.GraalCompiler#compileMethod} creates a {@link GraalCompilation} instance and then returns the result of calling its
- * {@link com.oracle.graal.compiler.GraalCompilation#compile} method.
- * <p>
- * While there is only one {@code GraalCompiler} instance, there may be several compilations proceeding concurrently, each of
- * which is represented by a unique {@code GraalCompilation} instance. The static method {@link com.oracle.graal.compiler.GraalCompilation#currentInterval}} returns the
- * {@code GraalCompilation} instance associated with the current thread, and is managed using a {@link java.lang.ThreadLocal} variable.
- * Each {@code GraalCompilation} instance has an associated {@link com.oracle.max.cri.ci.CiStatistics} object that accumulates information about the compilation process.
- * </p>
- * <H3>Supported backends</H3>
- *
- * <ul>
- * <li>AMD64/x64 with SSE2</li>
- * </ul>
+ * Graal is intended to be used with multiple JVM's so makes no use of or reference to classes for a specific JVM.
  */
 package com.oracle.graal.compiler;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertUnreachedToGuardPhase.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.compiler.phases;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.util.*;
+
+
+public class ConvertUnreachedToGuardPhase extends Phase {
+    private OptimisticOptimizations opt;
+
+    public ConvertUnreachedToGuardPhase(OptimisticOptimizations opt) {
+        this.opt = opt;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        if (!opt.removeNeverExecutedCode()) {
+            return;
+        }
+        for (Node node : graph.getNodes()) {
+            if (node instanceof IfNode) {
+                IfNode ifNode = (IfNode) node;
+                BeginNode insertGuard = null;
+                BeginNode delete = null;
+                boolean inverted = false;
+                if (ifNode.probability(IfNode.TRUE_EDGE) == 0) {
+                    insertGuard = ifNode.falseSuccessor();
+                    delete = ifNode.trueSuccessor();
+                    inverted = true;
+                } else if (ifNode.probability(IfNode.FALSE_EDGE) == 0) {
+                    insertGuard = ifNode.trueSuccessor();
+                    delete = ifNode.falseSuccessor();
+                }
+                if (insertGuard != null) {
+                    GuardNode guard = graph.unique(new GuardNode(ifNode.compare(), BeginNode.prevBegin(ifNode), DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile, inverted, ifNode.leafGraphId()));
+                    graph.addBeforeFixed(ifNode, graph.add(new ValueAnchorNode(guard)));
+                    GraphUtil.killCFG(delete);
+                    graph.removeSplit(ifNode, inverted ? IfNode.FALSE_EDGE : IfNode.TRUE_EDGE);
+                }
+            }
+        }
+
+    }
+
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Tue Jul 03 11:16:56 2012 +0200
@@ -28,7 +28,6 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.graph.*;
 import com.oracle.graal.compiler.util.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -191,13 +190,13 @@
     }
 
     private final TargetDescription target;
-    private final ExtendedRiRuntime runtime;
+    private final GraalCodeCacheProvider runtime;
     private final Assumptions assumptions;
-    private final RiGraphCache cache;
+    private final GraphCache cache;
     private final PhasePlan plan;
     private final OptimisticOptimizations optimisticOpts;
 
-    public EscapeAnalysisPhase(TargetDescription target, ExtendedRiRuntime runtime, Assumptions assumptions, RiGraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
+    public EscapeAnalysisPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
         this.runtime = runtime;
         this.target = target;
         this.assumptions = assumptions;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java	Tue Jul 03 11:16:56 2012 +0200
@@ -33,11 +33,11 @@
 import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.compiler.util.InliningUtil.InlineInfo;
 import com.oracle.graal.compiler.util.InliningUtil.InliningCallback;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 
 
 public class InliningPhase extends Phase implements InliningCallback {
@@ -48,7 +48,7 @@
      */
 
     private final TargetDescription target;
-    private final ExtendedRiRuntime runtime;
+    private final GraalCodeCacheProvider runtime;
 
     private final Collection<? extends Invoke> hints;
 
@@ -56,7 +56,7 @@
     private Assumptions assumptions;
 
     private final PhasePlan plan;
-    private final RiGraphCache cache;
+    private final GraphCache cache;
     private final WeightComputationPolicy weightComputationPolicy;
     private final InliningPolicy inliningPolicy;
     private final OptimisticOptimizations optimisticOpts;
@@ -66,7 +66,7 @@
     private static final DebugMetric metricInliningConsidered = Debug.metric("InliningConsidered");
     private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize");
 
-    public InliningPhase(TargetDescription target, ExtendedRiRuntime runtime, Collection<? extends Invoke> hints, Assumptions assumptions, RiGraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
+    public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Collection<? extends Invoke> hints, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
         this.target = target;
         this.runtime = runtime;
         this.hints = hints;
@@ -184,7 +184,6 @@
 
     @Override
     public StructuredGraph buildGraph(final ResolvedJavaMethod method) {
-        final StructuredGraph newGraph = new StructuredGraph(method);
 
         return Debug.scope("buildInlineGraph", this, new Callable<StructuredGraph>() {
 
@@ -196,8 +195,7 @@
                         return cachedGraph;
                     }
                 }
-
-
+                StructuredGraph newGraph = new StructuredGraph(method);
                 if (plan != null) {
                     plan.runPhases(PhasePosition.AFTER_PARSING, newGraph);
                 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/IntrinsificationPhase.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/IntrinsificationPhase.java	Tue Jul 03 11:16:56 2012 +0200
@@ -24,16 +24,16 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.util.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 
 public class IntrinsificationPhase extends Phase {
 
-    private final ExtendedRiRuntime runtime;
+    private final GraalCodeCacheProvider runtime;
 
-    public IntrinsificationPhase(ExtendedRiRuntime runtime) {
+    public IntrinsificationPhase(GraalCodeCacheProvider runtime) {
         this.runtime = runtime;
     }
 
@@ -47,18 +47,18 @@
         }
     }
 
-    public static boolean canIntrinsify(Invoke invoke, ResolvedJavaMethod target, ExtendedRiRuntime runtime) {
+    public static boolean canIntrinsify(Invoke invoke, ResolvedJavaMethod target, GraalCodeCacheProvider runtime) {
         return getIntrinsicGraph(invoke, target, runtime) != null;
     }
 
-    private static void tryIntrinsify(Invoke invoke, ExtendedRiRuntime runtime) {
+    private static void tryIntrinsify(Invoke invoke, GraalCodeCacheProvider runtime) {
         ResolvedJavaMethod target = invoke.callTarget().targetMethod();
         if (target != null) {
             tryIntrinsify(invoke, target, runtime);
         }
     }
 
-    private static void tryIntrinsify(Invoke invoke, ResolvedJavaMethod target, ExtendedRiRuntime runtime) {
+    private static void tryIntrinsify(Invoke invoke, ResolvedJavaMethod target, GraalCodeCacheProvider runtime) {
         StructuredGraph intrinsicGraph = getIntrinsicGraph(invoke, target, runtime);
         if (intrinsicGraph != null) {
             Debug.log(" > Intrinsify %s", target);
@@ -66,7 +66,7 @@
         }
     }
 
-    private static StructuredGraph getIntrinsicGraph(Invoke invoke, ResolvedJavaMethod target, ExtendedRiRuntime runtime) {
+    private static StructuredGraph getIntrinsicGraph(Invoke invoke, ResolvedJavaMethod target, GraalCodeCacheProvider runtime) {
         StructuredGraph intrinsicGraph = (StructuredGraph) target.compilerStorage().get(Graph.class);
         if (intrinsicGraph == null) {
             // TODO remove once all intrinsics are available via compilerStorage
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopFullUnrollPhase.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopFullUnrollPhase.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,16 +23,16 @@
 package com.oracle.graal.compiler.phases;
 
 import com.oracle.graal.compiler.loop.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 
 
 public class LoopFullUnrollPhase extends Phase {
     private static final DebugMetric FULLY_UNROLLED_LOOPS = Debug.metric("FullUnrolls");
-    private final ExtendedRiRuntime runtime;
+    private final GraalCodeCacheProvider runtime;
 
-    public LoopFullUnrollPhase(ExtendedRiRuntime runtime) {
+    public LoopFullUnrollPhase(GraalCodeCacheProvider runtime) {
         this.runtime = runtime;
     }
 
@@ -44,7 +44,7 @@
                 peeled = false;
                 final LoopsData dataCounted = new LoopsData(graph);
                 dataCounted.detectedCountedLoops();
-                for (final LoopEx loop : dataCounted.countedLoops()) {
+                for (LoopEx loop : dataCounted.countedLoops()) {
                     if (LoopPolicies.shouldFullUnroll(loop)) {
                         Debug.log("FullUnroll %s", loop);
                         LoopTransformations.fullUnroll(loop, runtime);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformLowPhase.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformLowPhase.java	Tue Jul 03 11:16:56 2012 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.nodes.*;
 
 public class LoopTransformLowPhase extends Phase {
+    private static final DebugMetric UNSWITCHED = Debug.metric("Unswitched");
 
     @Override
     protected void run(StructuredGraph graph) {
@@ -43,6 +44,26 @@
                     }
                 });
             }
+            if (GraalOptions.LoopUnswitch) {
+                boolean unswitched;
+                do {
+                    unswitched = false;
+                    final LoopsData dataUnswitch = new LoopsData(graph);
+                    for (LoopEx loop : dataUnswitch.loops()) {
+                        if (LoopPolicies.shouldTryUnswitch(loop)) {
+                            IfNode ifNode = LoopTransformations.findUnswitchableIf(loop);
+                            if (ifNode != null && LoopPolicies.shouldUnswitch(loop, ifNode)) {
+                                Debug.log("Unswitching %s at %s [%f - %f]", loop, ifNode, ifNode.probability(0), ifNode.probability(1));
+                                LoopTransformations.unswitch(loop, ifNode);
+                                UNSWITCHED.increment();
+                                Debug.dump(graph, "After unswitch %s", loop);
+                                unswitched = true;
+                                break;
+                            }
+                        }
+                    }
+                } while(unswitched);
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Tue Jul 03 11:16:56 2012 +0200
@@ -25,7 +25,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.cfg.*;
@@ -38,10 +37,10 @@
  */
 public class LoweringPhase extends Phase {
 
-    private class LoweringToolBase implements CiLoweringTool {
+    private class LoweringToolBase implements LoweringTool {
 
         @Override
-        public ExtendedRiRuntime getRuntime() {
+        public GraalCodeCacheProvider getRuntime() {
             return runtime;
         }
 
@@ -72,10 +71,10 @@
         }
     }
 
-    private final ExtendedRiRuntime runtime;
+    private final GraalCodeCacheProvider runtime;
     private final Assumptions assumptions;
 
-    public LoweringPhase(ExtendedRiRuntime runtime, Assumptions assumptions) {
+    public LoweringPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) {
         this.runtime = runtime;
         this.assumptions = assumptions;
     }
@@ -101,7 +100,7 @@
 
         // Step 2: lower the floating nodes
         processed.negate();
-        final CiLoweringTool loweringTool = new LoweringToolBase();
+        final LoweringTool loweringTool = new LoweringToolBase();
         for (Node node : processed) {
             if (node instanceof Lowerable) {
                 assert !(node instanceof FixedNode) || node.predecessor() == null : node;
@@ -142,7 +141,7 @@
 
     private void process(final Block b, final NodeBitMap activeGuards, NodeBitMap processed, final ValueNode anchor) {
 
-        final CiLoweringTool loweringTool = new LoweringToolBase() {
+        final LoweringTool loweringTool = new LoweringToolBase() {
 
             @Override
             public ValueNode getGuardAnchor() {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/SchedulePhase.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/SchedulePhase.java	Tue Jul 03 11:16:56 2012 +0200
@@ -111,9 +111,7 @@
     }
 
     /**
-     * Assigns a block to the given node. This method expects that PhiNodes and FixedNodes are already assigned to a
-     * block, since they should already have been placed by {@link ControlFlowGraph#identifyBlocks()}.
-     * This method will also try to
+     * Assigns a block to the given node. This method expects that PhiNodes and FixedNodes are already assigned to a block.
      */
     private void assignBlockToNode(ScheduledNode node) {
         assert !node.isDeleted();
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Tue Jul 03 11:16:56 2012 +0200
@@ -107,7 +107,7 @@
      * spilling callee-save registers, stack overflow checking, handling multiple entry
      * points etc. A suffix may contain out-of-line stubs and method end guard instructions.
      *
-     * @param the method associated with {@code lir}
+     * @param method the method associated with {@code lir}
      * @param lir the LIR of {@code method}
      */
     public abstract void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIR lir);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Tue Jul 03 11:16:56 2012 +0200
@@ -35,12 +35,12 @@
 
 public class AMD64DeoptimizationStub extends AMD64Code {
     public final Label label = new Label();
-    public final LIRDebugInfo info;
+    public final LIRFrameState info;
     public final DeoptimizationAction action;
     public final DeoptimizationReason reason;
     public final Object deoptInfo;
 
-    public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRDebugInfo info, Object deoptInfo) {
+    public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) {
         this.action = action;
         this.reason = reason;
         this.info = info;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Tue Jul 03 11:16:56 2012 +0200
@@ -54,12 +54,7 @@
 import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
 import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp;
 import com.oracle.graal.lir.amd64.AMD64Compare.CompareOp;
-import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp;
-import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
-import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatBranchOp;
-import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatCondMoveOp;
-import com.oracle.graal.lir.amd64.AMD64ControlFlow.ReturnOp;
-import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.*;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LeaOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
@@ -218,12 +213,12 @@
     }
 
     @Override
-    public void emitJump(LabelRef label, LIRDebugInfo info) {
+    public void emitJump(LabelRef label, LIRFrameState info) {
         append(new JumpOp(label, info));
     }
 
     @Override
-    public void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRDebugInfo info) {
+    public void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         switch (left.kind.stackKind()) {
@@ -525,7 +520,7 @@
 
     @Override
     public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) {
-        LIRDebugInfo info = state();
+        LIRFrameState info = state();
         LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo);
         append(new BranchOp(ConditionFlag.overflow, stubEntry, info));
     }
@@ -533,7 +528,7 @@
 
     @Override
     public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo, long leafGraphId) {
-        LIRDebugInfo info = state(leafGraphId);
+        LIRFrameState info = state(leafGraphId);
         LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo);
         append(new JumpOp(stubEntry, info));
     }
@@ -547,7 +542,7 @@
     }
 
     @Override
-    protected void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRDebugInfo info, Map<XirMark, Mark> marks) {
+    protected void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRFrameState info, Map<XirMark, Mark> marks) {
         if (isConstant(targetAddress)) {
             append(new DirectCallOp(targetMethod, result, arguments.toArray(new Value[arguments.size()]), info, marks));
         } else {
@@ -562,19 +557,35 @@
 
     @Override
     protected void emitXir(XirSnippet snippet, Value[] operands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex,
-                    LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) {
+                    LIRFrameState info, LIRFrameState infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) {
         append(new AMD64XirOp(snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, trueSuccessor, falseSuccessor));
     }
 
     @Override
-    protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value index) {
+    protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
         // Making a copy of the switch value is necessary because jump table destroys the input value
-        Variable tmp = emitMove(index);
+        if (key.kind == Kind.Int) {
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.IllegalValue));
+        } else {
+            assert key.kind == Kind.Object;
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object)));
+        }
+    }
+
+    @Override
+    protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) {
+        append(new SwitchRangesOp(lowKeys, highKeys, targets, defaultTarget, key));
+    }
+
+    @Override
+    protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
+        // Making a copy of the switch value is necessary because jump table destroys the input value
+        Variable tmp = emitMove(key);
         append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind)));
     }
 
     @Override
-    protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRDebugInfo info, Object deoptInfo) {
+    protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) {
         assert info.topFrame.getBCI() >= 0 : "invalid bci for deopt framestate";
         AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, reason, info, deoptInfo);
         lir.stubs.add(stub);
@@ -584,7 +595,7 @@
     @Override
     protected void emitNullCheckGuard(ValueNode object, long leafGraphId) {
         Variable value = load(operand(object));
-        LIRDebugInfo info = state(leafGraphId);
+        LIRFrameState info = state(leafGraphId);
         append(new NullCheckOp(value, info));
     }
 
@@ -599,7 +610,7 @@
         Address address;
         int displacement = node.displacement();
         Value index = operand(node.offset());
-        if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong())) {
+        if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) {
             displacement += (int) asConstant(index).asLong();
             address = new Address(kind, load(operand(node.object())), displacement);
         } else {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java	Tue Jul 03 11:16:56 2012 +0200
@@ -46,8 +46,8 @@
 
 public class AMD64XirOp extends LIRXirInstruction {
     public AMD64XirOp(XirSnippet snippet, Value[] operands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex,
-                        LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) {
-        super("XIR", snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, trueSuccessor, falseSuccessor);
+                        LIRFrameState info, LIRFrameState infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) {
+        super(snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, trueSuccessor, falseSuccessor);
     }
 
     @Override
@@ -165,7 +165,7 @@
                     Value pointer = operands[inst.x().index];
                     RegisterValue register = assureInRegister(tasm, masm, pointer);
 
-                    AMD64Move.load(tasm, masm, result, new Address(inst.kind, register), (Boolean) inst.extra ? info : null);
+                    AMD64Move.load(tasm, masm, result, new Address(inst.kind, register), (Boolean) inst.extra ? state : null);
                     break;
                 }
 
@@ -174,7 +174,7 @@
                     Value pointer = operands[inst.x().index];
                     assert isRegister(pointer);
 
-                    AMD64Move.store(tasm, masm, new Address(inst.kind, pointer), value, (Boolean) inst.extra ? info : null);
+                    AMD64Move.store(tasm, masm, new Address(inst.kind, pointer), value, (Boolean) inst.extra ? state : null);
                     break;
                 }
 
@@ -201,7 +201,7 @@
                         src = new Address(inst.kind, pointer, index, scale, displacement);
                     }
 
-                    AMD64Move.load(tasm, masm, result, src, canTrap ? info : null);
+                    AMD64Move.load(tasm, masm, result, src, canTrap ? state : null);
                     break;
                 }
 
@@ -245,7 +245,7 @@
                         dst = new Address(inst.kind, pointer, index, scale, displacement);
                     }
 
-                    AMD64Move.store(tasm, masm, dst, value, canTrap ? info : null);
+                    AMD64Move.store(tasm, masm, dst, value, canTrap ? state : null);
                     break;
                 }
 
@@ -271,8 +271,8 @@
                     RegisterValue pointerRegister = assureInRegister(tasm, masm, exchangedAddress);
                     Address addr = new Address(tasm.target.wordKind, pointerRegister);
 
-                    if ((Boolean) inst.extra && info != null) {
-                        tasm.recordImplicitException(masm.codeBuffer.position(), info);
+                    if ((Boolean) inst.extra && state != null) {
+                        tasm.recordImplicitException(masm.codeBuffer.position(), state);
                     }
                     masm.cmpxchgq(asRegister(exchangedVal), addr);
 
@@ -294,7 +294,7 @@
                     }
 
                     RuntimeCallInformation runtimeCallInformation = (RuntimeCallInformation) inst.extra;
-                    AMD64Call.directCall(tasm, masm, runtimeCallInformation.target, (runtimeCallInformation.useInfoAfter) ? infoAfter : info);
+                    AMD64Call.directCall(tasm, masm, runtimeCallInformation.target, (runtimeCallInformation.useInfoAfter) ? stateAfter : state);
 
                     if (inst.result != null && inst.result.kind != Kind.Illegal && inst.result.kind != Kind.Void) {
                         Register returnRegister = tasm.frameMap.registerConfig.getReturnRegister(inst.result.kind);
@@ -386,12 +386,12 @@
                     break;
                 }
                 case Safepoint: {
-                    assert info != null : "Must have debug info in order to create a safepoint.";
-                    tasm.recordSafepoint(masm.codeBuffer.position(), info);
+                    assert state != null : "Must have debug info in order to create a safepoint.";
+                    tasm.recordSafepoint(masm.codeBuffer.position(), state);
                     break;
                 }
                 case NullCheck: {
-                    tasm.recordImplicitException(masm.codeBuffer.position(), info);
+                    tasm.recordImplicitException(masm.codeBuffer.position(), state);
                     Value pointer = operands[inst.x().index];
                     masm.nullCheck(asRegister(pointer));
                     break;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/BlockWorkList.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/BlockWorkList.java	Tue Jul 03 11:16:56 2012 +0200
@@ -29,11 +29,6 @@
  * operate either as a stack (i.e. first-in / last-out), or as a sorted list,
  * where blocks can be sorted by a supplied number. The latter usage lends itself
  * naturally to iterative dataflow analysis problems.
- *
- * This implementation is not able to tell if a block is in the worklist already.
- * Note that this implementation is slightly less efficient than the dedicated
- * work list in {@link com.oracle.graal.compiler.graph.ScopeData}, because this worklist uses
- * an externally supplied number.
  */
 public class BlockWorkList {
     MergeNode[] workList;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Tue Jul 03 11:16:56 2012 +0200
@@ -31,7 +31,6 @@
 import com.oracle.graal.api.meta.JavaTypeProfile.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -40,6 +39,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
@@ -56,9 +56,9 @@
         if (!Debug.isLogEnabled()) {
             return null;
         } else if (invoke != null && invoke.stateAfter() != null) {
-            return methodName(invoke.stateAfter(), invoke.bci()) + ": " + CodeUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
+            return methodName(invoke.stateAfter(), invoke.bci()) + ": " + MetaUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
         } else {
-            return CodeUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
+            return MetaUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
         }
     }
 
@@ -78,7 +78,7 @@
             sb.append(methodName(frameState.outerFrameState(), frameState.outerFrameState().bci));
             sb.append("->");
         }
-        sb.append(CodeUtil.format("%h.%n", frameState.method()));
+        sb.append(MetaUtil.format("%h.%n", frameState.method()));
         sb.append("@").append(bci);
         return sb.toString();
     }
@@ -125,7 +125,7 @@
          * @param runtime
          * @param callback
          */
-        public abstract void inline(StructuredGraph graph, ExtendedRiRuntime runtime, InliningCallback callback);
+        public abstract void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback);
     }
 
     /**
@@ -141,7 +141,7 @@
         }
 
         @Override
-        public void inline(StructuredGraph compilerGraph, ExtendedRiRuntime runtime, final InliningCallback callback) {
+        public void inline(StructuredGraph compilerGraph, GraalCodeCacheProvider runtime, final InliningCallback callback) {
             StructuredGraph graph = getGraph(concrete, callback);
             assert !IntrinsificationPhase.canIntrinsify(invoke, concrete, runtime);
             callback.recordMethodContentsAssumption(concrete);
@@ -155,7 +155,7 @@
 
         @Override
         public String toString() {
-            return "exact " + CodeUtil.format("%H.%n(%p):%r", concrete);
+            return "exact " + MetaUtil.format("%H.%n(%p):%r", concrete);
         }
 
         @Override
@@ -184,7 +184,7 @@
         }
 
         @Override
-        public void inline(StructuredGraph graph, ExtendedRiRuntime runtime, InliningCallback callback) {
+        public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
             // receiver null check must be before the type check
             InliningUtil.receiverNullCheck(invoke);
             ValueNode receiver = invoke.callTarget().receiver();
@@ -209,7 +209,7 @@
 
         @Override
         public String toString() {
-            return "type-checked " + CodeUtil.format("%H.%n(%p):%r", concrete);
+            return "type-checked " + MetaUtil.format("%H.%n(%p):%r", concrete);
         }
 
         @Override
@@ -250,7 +250,7 @@
         }
 
         @Override
-        public void inline(StructuredGraph graph, ExtendedRiRuntime runtime, InliningCallback callback) {
+        public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
             int numberOfMethods = concretes.size();
             boolean hasReturnValue = invoke.node().kind() != Kind.Void;
 
@@ -267,7 +267,7 @@
             return notRecordedTypeProbability > 0;
         }
 
-        private void inlineMultipleMethods(StructuredGraph graph, ExtendedRiRuntime runtime, InliningCallback callback, int numberOfMethods, boolean hasReturnValue) {
+        private void inlineMultipleMethods(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, int numberOfMethods, boolean hasReturnValue) {
             FixedNode continuation = invoke.next();
 
             // setup merge and phi nodes for results and exceptions
@@ -373,7 +373,7 @@
             return commonType;
         }
 
-        private void inlineSingleMethod(StructuredGraph graph, ExtendedRiRuntime runtime, InliningCallback callback) {
+        private void inlineSingleMethod(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
             assert concretes.size() == 1 && ptypes.length > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
 
             MergeNode calleeEntryNode = graph.add(new MergeNode());
@@ -401,7 +401,7 @@
             ResolvedJavaType[] types = new ResolvedJavaType[ptypes.length];
             double[] probabilities = new double[ptypes.length + 1];
             BeginNode[] successors = new BeginNode[ptypes.length + 1];
-
+            int[] keySuccessors = new int[ptypes.length + 1];
             for (int i = 0; i < ptypes.length; i++) {
                 types[i] = ptypes[i].type;
                 probabilities[i] = ptypes[i].probability;
@@ -412,12 +412,14 @@
                     entry = endNode;
                 }
                 successors[i] = BeginNode.begin(entry);
+                keySuccessors[i] = i;
             }
             assert !(unknownTypeSux instanceof MergeNode);
             successors[successors.length - 1] = BeginNode.begin(unknownTypeSux);
             probabilities[successors.length - 1] = notRecordedTypeProbability;
+            keySuccessors[successors.length - 1] = successors.length - 1;
 
-            TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(objectClassNode, successors, types, probabilities));
+            TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(objectClassNode, successors, probabilities, types, probabilities, keySuccessors));
 
             return typeSwitch;
         }
@@ -485,7 +487,7 @@
             StringBuilder builder = new StringBuilder(shouldFallbackToInvoke() ? "megamorphic" : "polymorphic");
             builder.append(String.format(", %d methods with %d type checks:", concretes.size(), ptypes.length));
             for (int i = 0; i < concretes.size(); i++) {
-                builder.append(CodeUtil.format("  %H.%n(%p):%r", concretes.get(i)));
+                builder.append(MetaUtil.format("  %H.%n(%p):%r", concretes.get(i)));
             }
             return builder.toString();
         }
@@ -510,10 +512,10 @@
         }
 
         @Override
-        public void inline(StructuredGraph graph, ExtendedRiRuntime runtime, InliningCallback callback) {
+        public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
             if (Debug.isLogEnabled()) {
-                String targetName = CodeUtil.format("%H.%n(%p):%r", invoke.callTarget().targetMethod());
-                String concreteName = CodeUtil.format("%H.%n(%p):%r", concrete);
+                String targetName = MetaUtil.format("%H.%n(%p):%r", invoke.callTarget().targetMethod());
+                String concreteName = MetaUtil.format("%H.%n(%p):%r", concrete);
                 Debug.log("recording concrete method assumption: %s on receiver type %s -> %s", targetName, context, concreteName);
             }
             callback.recordConcreteMethodAssumption(invoke.callTarget().targetMethod(), context, concrete);
@@ -523,7 +525,7 @@
 
         @Override
         public String toString() {
-            return "assumption " + CodeUtil.format("%H.%n(%p):%r", concrete);
+            return "assumption " + MetaUtil.format("%H.%n(%p):%r", concrete);
         }
 
         @Override
@@ -540,7 +542,7 @@
      * @param callback a callback that is used to determine the weight of a specific inlining
      * @return an instance of InlineInfo, or null if no inlining is possible at the given invoke
      */
-    public static InlineInfo getInlineInfo(Invoke invoke, int level, ExtendedRiRuntime runtime, Assumptions assumptions, InliningCallback callback, OptimisticOptimizations optimisticOpts) {
+    public static InlineInfo getInlineInfo(Invoke invoke, int level, GraalCodeCacheProvider runtime, Assumptions assumptions, InliningCallback callback, OptimisticOptimizations optimisticOpts) {
         ResolvedJavaMethod parent = invoke.stateAfter().method();
         MethodCallTargetNode callTarget = invoke.callTarget();
         ResolvedJavaMethod targetMethod = callTarget.targetMethod();
@@ -780,12 +782,15 @@
             } else {
                 nodes.add(node);
                 if (node instanceof ReturnNode) {
+                    assert returnNode == null;
                     returnNode = (ReturnNode) node;
                 } else if (node instanceof UnwindNode) {
+                    assert unwindNode == null;
                     unwindNode = (UnwindNode) node;
                 }
             }
         }
+        replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node())); // ensure proper anchoring of things that where anchored to the StartNode
 
         assert invoke.node().successors().first() != null : invoke;
         assert invoke.node().predecessor() != null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.debug</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.examples/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.examples</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.graph.test</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.graph</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Jul 03 11:16:56 2012 +0200
@@ -109,7 +109,7 @@
     /**
      * Creates a copy of this graph.
      *
-     * @param name the name of the copy, used for debugging purposes (can be null)
+     * @param newName the name of the copy, used for debugging purposes (can be null)
      */
     public Graph copy(String newName) {
         Graph copy = new Graph(newName);
@@ -235,7 +235,7 @@
     }
 
     /**
-     * Gets a mark that can be used with {@link #getNewNodes()}.
+     * Gets a mark that can be used with {@link #getNewNodes(int)}.
      */
     public int getMark() {
         return nodeIdCount();
@@ -526,7 +526,7 @@
      * regarding the matching of node types in the replacement map.
      *
      * @param newNodes the nodes to be duplicated
-     * @param replacements the replacement map (can be null if no replacement is to be performed)
+     * @param replacementsMap the replacement map (can be null if no replacement is to be performed)
      * @return a map which associates the original nodes from {@code nodes} to their duplicates
      */
     public Map<Node, Node> addDuplicates(Iterable<Node> newNodes, Map<Node, Node> replacementsMap) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Jul 03 11:16:56 2012 +0200
@@ -35,8 +35,6 @@
  * with annotated fields. There are two kind of edges : {@link Input} and {@link Successor}. If a field, of a type
  * compatible with {@link Node}, annotated with either {@link Input} and {@link Successor} is not null, then there is an
  * edge from this node to the node this field points to.<br>
- * Fields in a node subclass can also be annotated with {@link Data} : such fields will be used when comparing 2 nodes
- * with {@link #equals(Object)}, for value numbering and for debugging purposes.<br>
  * Nodes which are be value numberable should implement the {@link ValueNumberable} interface.
  *
  * <h1>Assertions and Verification</h1>
@@ -45,8 +43,6 @@
  * {@link #assertFalse(boolean, String, Object...)} methods, which will check the supplied boolean and throw a
  * VerificationError if it has the wrong value. Both methods will always either throw an exception or return true.
  * They can thus be used within an assert statement, so that the check is only performed if assertions are enabled.
- *
- *
  */
 public abstract class Node implements Cloneable, Formattable {
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Jul 03 11:16:56 2012 +0200
@@ -408,8 +408,9 @@
     }
 
     /**
-     * An iterator that will iterate over the fields given in {@link offsets}.
-     * The first {@ directCount} offsets are treated as fields of type {@link Node}, while the rest of the fields are treated as {@link NodeList}s.
+     * An iterator that will iterate over the fields given in {@link #offsets}.
+     * The first {@link #directCount} offsets are treated as fields of type {@link Node},
+     * while the rest of the fields are treated as {@link NodeList}s.
      * All elements of these NodeLists will be visited by the iterator as well.
      * This iterator can be used to iterate over the inputs or successors of a node.
      *
@@ -546,7 +547,8 @@
     }
 
     /**
-     * Populates a given map with the names and values of all fields marked with @{@link Data}.
+     * Populates a given map with the names and values of all data fields.
+     *
      * @param node the node from which to take the values.
      * @param properties a map that will be populated.
      */
@@ -952,7 +954,7 @@
                             replacementsMap.put(input, replacement);
                             assert replacement == null || node.getNodeClass().inputTypes[pos.index] == null || node.getNodeClass().inputTypes[pos.index].isAssignableFrom(replacement.getClass());
                             target = replacement;
-                        } else { // patch to the outer world
+                        } else if (input.graph() == graph) { // patch to the outer world
                             target = input;
                         }
                     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.server/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.hotspot.server</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.hotspot</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java	Tue Jul 03 11:16:56 2012 +0200
@@ -78,9 +78,9 @@
 
     private CompilationStatistics(ResolvedJavaMethod method) {
         if (method != null) {
-            holder = CodeUtil.format("%H", method);
+            holder = MetaUtil.format("%H", method);
             name = method.name();
-            signature = CodeUtil.format("%p", method);
+            signature = MetaUtil.format("%p", method);
             startTime = System.nanoTime();
             startInvCount = method.invocationCount();
             bytecodeCount = method.codeSize();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Jul 03 11:16:56 2012 +0200
@@ -131,11 +131,11 @@
         } catch (BailoutException bailout) {
             Debug.metric("Bailouts").increment();
             if (GraalOptions.ExitVMOnBailout) {
-                TTY.cachedOut.println(CodeUtil.format("Bailout in %H.%n(%p)", method));
+                TTY.cachedOut.println(MetaUtil.format("Bailout in %H.%n(%p)", method));
                 bailout.printStackTrace(TTY.cachedOut);
                 System.exit(-1);
             } else if (GraalOptions.PrintBailout) {
-                TTY.cachedOut.println(CodeUtil.format("Bailout in %H.%n(%p)", method));
+                TTY.cachedOut.println(MetaUtil.format("Bailout in %H.%n(%p)", method));
                 bailout.printStackTrace(TTY.cachedOut);
             }
         } catch (Throwable t) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Jul 03 11:16:56 2012 +0200
@@ -28,10 +28,10 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.cri.xir.*;
 
@@ -204,7 +204,7 @@
     @SuppressWarnings("unchecked")
     @Override
     public <T> T getCapability(Class<T> clazz) {
-        if (clazz == ExtendedRiRuntime.class || clazz == MetaAccessProvider.class) {
+        if (clazz == GraalCodeCacheProvider.class || clazz == MetaAccessProvider.class) {
             return (T) getRuntime();
         }
         if (clazz == GraalCompiler.class) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Jul 03 11:16:56 2012 +0200
@@ -223,9 +223,9 @@
     }
 
     private void enqueue(Method m) throws Throwable {
-        JavaMethod riMethod = compiler.getRuntime().getResolvedJavaMethod(m);
-        assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) riMethod).accessFlags()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) riMethod).accessFlags()) : riMethod;
-        compileMethod((HotSpotResolvedJavaMethod) riMethod, 0, false, 10);
+        JavaMethod javaMethod = compiler.getRuntime().getResolvedJavaMethod(m);
+        assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) javaMethod).accessFlags()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) javaMethod).accessFlags()) : javaMethod;
+        compileMethod((HotSpotResolvedJavaMethod) javaMethod, 0, false, 10);
     }
 
     private static void shutdownCompileQueue(ThreadPoolExecutor queue) throws InterruptedException {
@@ -412,7 +412,7 @@
             HotSpotResolvedJavaType resolved = (HotSpotResolvedJavaType) holder;
             return resolved.createRiField(name, type, offset, flags);
         }
-        return new BaseUnresolvedField(holder, name, type);
+        return new UnresolvedField(holder, name, type);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java	Tue Jul 03 11:16:56 2012 +0200
@@ -32,9 +32,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.*;
@@ -42,7 +41,6 @@
 import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.max.criutils.*;
 
-
 public class MethodEntryCounters {
     protected static final class Counter implements Comparable<Counter> {
         protected static ArrayList<Counter> counters = new ArrayList<>();
@@ -53,7 +51,7 @@
         protected long sortCount;
 
         protected Counter(ResolvedJavaMethod method) {
-            this.method = CodeUtil.format("%H.%n", method);
+            this.method = MetaUtil.format("%H.%n", method);
             counters.add(this);
         }
 
@@ -64,23 +62,24 @@
     }
 
 
+    @Opcode("ENTRY_COUNTER")
     protected static class AMD64MethodEntryOp extends AMD64LIRInstruction {
+        @Temp protected Value counterArr;
+        @Temp protected Value callerPc;
+
         protected static int codeSize;
 
         protected final Counter counter;
 
         protected AMD64MethodEntryOp(Counter counter, Value counterArr, Value callerPc) {
-            super("ENTRY_COUNTER", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, new Value[] {counterArr, callerPc});
             this.counter = counter;
+            this.counterArr = counterArr;
+            this.callerPc = callerPc;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
             int start = masm.codeBuffer.position();
-
-            Value counterArr = temp(0);
-            Value callerPc = temp(1);
-
             int off = Unsafe.getUnsafe().arrayBaseOffset(long[].class);
             int scale = Unsafe.getUnsafe().arrayIndexScale(long[].class);
 
@@ -114,16 +113,6 @@
             assert codeSize == 0 || codeSize == size;
             codeSize = size;
         }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Temp && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Temp && index == 1) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
-        }
     }
 
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompiledMethod.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompiledMethod.java	Tue Jul 03 11:16:56 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.lang.reflect.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 
@@ -70,14 +69,14 @@
     }
 
     private boolean checkArgs(Object... args) {
-        Kind[] sig = CodeUtil.signatureToKinds(method);
-        assert args.length == sig.length : CodeUtil.format("%H.%n(%p): expected ", method) + sig.length + " args, got " + args.length;
+        Kind[] sig = MetaUtil.signatureToKinds(method);
+        assert args.length == sig.length : MetaUtil.format("%H.%n(%p): expected ", method) + sig.length + " args, got " + args.length;
         for (int i = 0; i < sig.length; i++) {
             Object arg = args[i];
             if (arg == null) {
-                assert sig[i].isObject() : CodeUtil.format("%H.%n(%p): expected arg ", method) + i + " to be Object, not " + sig[i];
+                assert sig[i].isObject() : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be Object, not " + sig[i];
             } else if (!sig[i].isObject()) {
-                assert sig[i].toBoxedJavaClass() == arg.getClass() : CodeUtil.format("%H.%n(%p): expected arg ", method) + i + " to be " + sig[i] + ", not " + arg.getClass();
+                assert sig[i].toBoxedJavaClass() == arg.getClass() : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be " + sig[i] + ", not " + arg.getClass();
             }
         }
         return true;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Tue Jul 03 11:16:56 2012 +0200
@@ -29,8 +29,8 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 
 /**
  * This class implements the graph caching system for the HotSpot platform.
@@ -51,7 +51,7 @@
  * The {@link #cachedGraphIds} map is used to find the graphs that should be removed because of deoptimization, and to
  * enforce the graph cache size restriction.
  */
-public class HotSpotGraphCache implements RiGraphCache {
+public class HotSpotGraphCache implements GraphCache {
 
     private static final PrintStream out = System.out;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.*;
@@ -149,6 +148,6 @@
 
     @Override
     public String toString() {
-        return "HotSpotProfilingInfo<" + CodeUtil.profileToString(this, null, "; ") + ">";
+        return "HotSpotProfilingInfo<" + MetaUtil.profileToString(this, null, "; ") + ">";
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Jul 03 11:16:56 2012 +0200
@@ -26,7 +26,6 @@
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaType.*;
 import com.oracle.graal.compiler.*;
@@ -126,7 +125,7 @@
 
     @Override
     public String toString() {
-        return "HotSpotField<" + CodeUtil.format("%h.%n", this) + ":" + offset + ">";
+        return "HotSpotField<" + MetaUtil.format("%h.%n", this) + ":" + offset + ">";
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,19 +22,16 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import java.io.*;
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.counters.*;
-import com.oracle.max.criutils.*;
 
 /**
  * Implementation of RiMethod for resolved HotSpot methods.
@@ -164,7 +161,7 @@
 
     @Override
     public String toString() {
-        return "HotSpotMethod<" + CodeUtil.format("%h.%n", this) + ">";
+        return "HotSpotMethod<" + MetaUtil.format("%h.%n", this) + ">";
     }
 
     public boolean hasCompiledCode() {
@@ -201,59 +198,9 @@
         return compilationComplexity;
     }
 
-    private static final MethodFilter profilingInfoFilter = GraalOptions.PIFilter == null ? null : new MethodFilter(GraalOptions.PIFilter);
-
-    /**
-     * Determines if the profiling info cache should be used for this method.
-     */
-    private boolean useProfilingInfoCache() {
-        return GraalOptions.PICache != null && (profilingInfoFilter == null || profilingInfoFilter.matches(this));
-    }
-
-    private ProfilingInfo loadProfilingInfo() {
-        if (!useProfilingInfoCache()) {
-            return null;
-        }
-        synchronized (this) {
-            File file = new File(GraalOptions.PICache, JniMangle.mangleMethod(holder, name, signature(), false));
-            if (file.exists()) {
-                try {
-                    SnapshotProfilingInfo snapshot = SnapshotProfilingInfo.load(file, HotSpotGraalRuntime.getInstance().getRuntime());
-                    if (snapshot.codeSize() != codeSize) {
-                        // The class file was probably changed - ignore the saved profile
-                        return null;
-                    }
-                    return snapshot;
-                } catch (Exception e) {
-                    // ignore
-                }
-            }
-            return null;
-        }
-    }
-
-    private void saveProfilingInfo(ProfilingInfo info) {
-        if (useProfilingInfoCache()) {
-            synchronized (this) {
-                String base = JniMangle.mangleMethod(holder, name, signature(), false);
-                File file = new File(GraalOptions.PICache, base);
-                File txtFile = new File(GraalOptions.PICache, base + ".txt");
-                SnapshotProfilingInfo snapshot = info instanceof SnapshotProfilingInfo ? (SnapshotProfilingInfo) info : new SnapshotProfilingInfo(info);
-                try {
-                    snapshot.save(file, txtFile);
-                } catch (IOException e) {
-                    // ignore
-                }
-            }
-        }
-    }
-
     @Override
     public ProfilingInfo profilingInfo() {
-        ProfilingInfo info = loadProfilingInfo();
-        if (info != null) {
-            return info;
-        }
+        ProfilingInfo info;
 
         if (GraalOptions.UseProfilingInformation && methodData == null) {
             methodData = HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_methodData(this);
@@ -261,10 +208,9 @@
 
         if (methodData == null || (!methodData.hasNormalData() && !methodData.hasExtraData())) {
             // Be optimistic and return false for exceptionSeen. A methodDataOop is allocated in case of a deoptimization.
-            info = BaseProfilingInfo.get(ExceptionSeen.FALSE);
+            info = DefaultProfilingInfo.get(ExceptionSeen.FALSE);
         } else {
             info = new HotSpotProfilingInfo(methodData, codeSize);
-            saveProfilingInfo(info);
         }
         return info;
     }
@@ -314,7 +260,7 @@
 
     private Method toJava() {
         try {
-            return holder.toJava().getDeclaredMethod(name, CodeUtil.signatureToTypes(signature(), holder));
+            return holder.toJava().getDeclaredMethod(name, MetaUtil.signatureToTypes(signature(), holder));
         } catch (NoSuchMethodException e) {
             return null;
         }
@@ -322,7 +268,7 @@
 
     private Constructor toJavaConstructor() {
         try {
-            return holder.toJava().getDeclaredConstructor(CodeUtil.signatureToTypes(signature(), holder));
+            return holder.toJava().getDeclaredConstructor(MetaUtil.signatureToTypes(signature(), holder));
         } catch (NoSuchMethodException e) {
             return null;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.max.cri.util.MemoryBarriers.*;
+import static com.oracle.max.criutils.MemoryBarriers.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -34,7 +34,6 @@
 import com.oracle.graal.api.meta.JavaType.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.nodes.*;
@@ -44,6 +43,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.max.criutils.*;
@@ -51,7 +51,7 @@
 /**
  * CRI runtime implementation for the HotSpot VM.
  */
-public class HotSpotRuntime implements ExtendedRiRuntime {
+public class HotSpotRuntime implements GraalCodeCacheProvider {
     public final HotSpotVMConfig config;
     final HotSpotRegisterConfig regConfig;
     private final HotSpotRegisterConfig globalStubRegConfig;
@@ -227,7 +227,7 @@
     }
 
     @Override
-    public void lower(Node n, CiLoweringTool tool) {
+    public void lower(Node n, LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) n.graph();
         if (n instanceof ArrayLengthNode) {
             ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n;
@@ -345,12 +345,21 @@
         } else if (n instanceof UnsafeStoreNode) {
             UnsafeStoreNode store = (UnsafeStoreNode) n;
             IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.storeKind(), store.displacement(), store.offset(), graph, false);
-            WriteNode write = graph.add(new WriteNode(store.object(), store.value(), location));
+            ValueNode object = store.object();
+            WriteNode write = graph.add(new WriteNode(object, store.value(), location));
             write.setStateAfter(store.stateAfter());
             graph.replaceFixedWithFixed(store, write);
             if (write.value().kind() == Kind.Object && !write.value().isNullConstant()) {
-                FieldWriteBarrier barrier = graph.add(new FieldWriteBarrier(write.object()));
-                graph.addBeforeFixed(write, barrier);
+                ResolvedJavaType type = object.objectStamp().type();
+                WriteBarrier writeBarrier;
+                if (type != null && !type.isArrayClass() && type.toJava() != Object.class) {
+                    // Use a field write barrier since it's not an array store
+                    writeBarrier = graph.add(new FieldWriteBarrier(object));
+                } else {
+                    // This may be an array store so use an array write barrier
+                    writeBarrier = graph.add(new ArrayWriteBarrier(object, location));
+                }
+                graph.addAfterFixed(write, writeBarrier);
             }
         } else if (n instanceof ReadHubNode) {
             ReadHubNode objectClassNode = (ReadHubNode) n;
@@ -381,7 +390,7 @@
                 return true;
             }
             ResolvedJavaMethod method = graph.method();
-            return method != null && CodeUtil.format("%H.%n", method).contains(option);
+            return method != null && MetaUtil.format("%H.%n", method).contains(option);
         }
         return false;
     }
@@ -394,7 +403,7 @@
         return safeRead(array.graph(), Kind.Int, array, config.arrayLengthOffset, StampFactory.positiveInt(), leafGraphId);
     }
 
-    private static ValueNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) {
+    private static ValueNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) n.graph();
         ArrayLengthNode arrayLength = graph.add(new ArrayLengthNode(n.array()));
         ValueNode guard = tool.createGuard(graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), DeoptimizationReason.BoundsCheckException, DeoptimizationAction.InvalidateReprofile, n.leafGraphId());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java	Tue Jul 03 11:16:56 2012 +0200
@@ -44,7 +44,6 @@
 import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
 import com.oracle.max.cri.xir.CiXirAssembler.XirOperand;
 import com.oracle.max.cri.xir.CiXirAssembler.XirParameter;
-import com.oracle.max.criutils.*;
 
 public class HotSpotXirGenerator implements RiXirGenerator {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -54,7 +53,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Tue Jul 03 11:16:56 2012 +0200
@@ -62,7 +62,7 @@
     public void generate(LIRGenerator gen) {
         Variable result = gen.newVariable(Kind.Object);
         gen.emitMove(gen.operand(hub), AMD64.rdx.asValue(Kind.Object));
-        LIRDebugInfo info = gen.state();
+        LIRFrameState info = gen.state();
         AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue(Kind.Object), info);
         gen.append(op);
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -47,7 +46,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -61,7 +61,7 @@
         ResolvedJavaMethod method = frameState.method();
         boolean isStatic = Modifier.isStatic(method.accessFlags());
 
-        Kind[] signature = CodeUtil.signatureToKinds(method.signature(), isStatic ? null : method.holder().kind());
+        Kind[] signature = MetaUtil.signatureToKinds(method.signature(), isStatic ? null : method.holder().kind());
         CallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, signature, gen.target(), false);
         gen.frameMap().callsMethod(cc, CallingConvention.Type.JavaCall); // TODO (aw): I think this is unnecessary for a tail call.
         List<ValueNode> parameters = new ArrayList<>();
@@ -72,6 +72,6 @@
 
         Value entry = gen.emitLoad(new Address(Kind.Long, gen.operand(target), config.nmethodEntryOffset), false);
 
-        gen.append(new AMD64TailcallOp(argList, entry, cc.locations));
+        gen.append(new AMD64TailcallOp(argList, entry));
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Tue Jul 03 11:16:56 2012 +0200
@@ -45,7 +45,7 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        LIRDebugInfo info = gen.state();
+        LIRFrameState info = gen.state();
         AMD64VerifyOopStubCallOp op = new AMD64VerifyOopStubCallOp(gen.operand(object), info);
         gen.append(op);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Tue Jul 03 11:16:56 2012 +0200
@@ -117,9 +117,9 @@
         long srcOffset = srcPos * arrayIndexScale(baseKind);
         long destOffset = destPos * arrayIndexScale(baseKind);
         if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i -= arrayIndexScale(Kind.Char)) {
+                Character a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Char);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.charValue(), Kind.Char);
             }
             long vectorLength = byteLength - nonVectorBytes;
             for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
@@ -127,9 +127,9 @@
                 UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
             }
         } else {
-            for (long i = 0; i < nonVectorBytes; i++) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Char)) {
+                Character a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Char);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.charValue(), Kind.Char);
             }
             for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
                 Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
@@ -153,9 +153,9 @@
         long srcOffset = srcPos * arrayIndexScale(baseKind);
         long destOffset = destPos * arrayIndexScale(baseKind);
         if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i -= arrayIndexScale(Kind.Short)) {
+                Short a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Short);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.shortValue(), Kind.Short);
             }
             long vectorLength = byteLength - nonVectorBytes;
             for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
@@ -163,9 +163,9 @@
                 UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
             }
         } else {
-            for (long i = 0; i < nonVectorBytes; i++) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Short)) {
+                Short a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Short);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.shortValue(), Kind.Short);
             }
             for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
                 Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
@@ -189,9 +189,9 @@
         long srcOffset = srcPos * arrayIndexScale(baseKind);
         long destOffset = destPos * arrayIndexScale(baseKind);
         if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i -= arrayIndexScale(Kind.Int)) {
+                Integer a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Int);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.intValue(), Kind.Int);
             }
             long vectorLength = byteLength - nonVectorBytes;
             for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
@@ -199,9 +199,9 @@
                 UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
             }
         } else {
-            for (long i = 0; i < nonVectorBytes; i++) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Int)) {
+                Integer a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Int);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.intValue(), Kind.Int);
             }
             for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
                 Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
@@ -225,9 +225,9 @@
         long srcOffset = srcPos * arrayIndexScale(baseKind);
         long destOffset = destPos * arrayIndexScale(baseKind);
         if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i -= arrayIndexScale(Kind.Float)) {
+                Float a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Float);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.floatValue(), Kind.Float);
             }
             long vectorLength = byteLength - nonVectorBytes;
             for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
@@ -235,9 +235,9 @@
                 UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
             }
         } else {
-            for (long i = 0; i < nonVectorBytes; i++) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Float)) {
+                Float a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Float);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.floatValue(), Kind.Float);
             }
             for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
                 Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
@@ -308,18 +308,24 @@
             throw new IndexOutOfBoundsException();
         }
         final int scale = arrayIndexScale(Kind.Object);
+        int header = arrayBaseOffset(Kind.Object);
         if (src == dest && srcPos < destPos) { // bad aliased case
-            copyObjectsDown(src, srcPos * scale, dest, destPos * scale, length);
+            for (long i = (length - 1) * scale; i >= 0; i -= scale) {
+                Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
+                DirectObjectStoreNode.store(dest, header, i + (long) destPos * scale, a);
+            }
         } else {
-            copyObjectsUp(src, srcPos * scale, dest, destPos * scale, length);
+            for (long i = 0; i < length * scale; i += scale) {
+                Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
+                DirectObjectStoreNode.store(dest, header, i + (long) destPos * scale, a);
+            }
         }
         if (length > 0) {
-            int header = arrayBaseOffset(Kind.Object);
             int cardShift = cardTableShift();
             long cardStart = cardTableStart();
             long dstAddr = GetObjectAddressNode.get(dest);
-            long start = (dstAddr + header + destPos * scale) >>> cardShift;
-            long end = (dstAddr + header + (destPos + length - 1) * scale) >>> cardShift;
+            long start = (dstAddr + header + (long) destPos * scale) >>> cardShift;
+            long end = (dstAddr + header + ((long) destPos + length - 1) * scale) >>> cardShift;
             long count = end - start + 1;
             while (count-- > 0) {
                 DirectStoreNode.store((start + cardStart) + count, false);
@@ -327,28 +333,6 @@
         }
     }
 
-    // Does NOT perform store checks
-    @Snippet
-    public static void copyObjectsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        int header = arrayBaseOffset(Kind.Object);
-        final int scale = arrayIndexScale(Kind.Object);
-        for (long i = (length - 1) * scale; i >= 0; i -= scale) {
-            Object a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Object);
-            DirectObjectStoreNode.store(dest, header, i + destOffset, a);
-        }
-    }
-
-    // Does NOT perform store checks
-    @Snippet
-    public static void copyObjectsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        int header = arrayBaseOffset(Kind.Object);
-        final int scale = arrayIndexScale(Kind.Object);
-        for (long i = 0; i < length * scale; i += scale) {
-            Object a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Object);
-            DirectObjectStoreNode.store(dest, header, i + destOffset, a);
-        }
-    }
-
     @Fold
     static int arrayBaseOffset(Kind elementKind) {
         return elementKind.arrayBaseOffset();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Tue Jul 03 11:16:56 2012 +0200
@@ -34,7 +34,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
@@ -42,6 +41,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
 import com.oracle.graal.snippets.Snippet.Fold;
@@ -50,7 +50,6 @@
 import com.oracle.graal.snippets.SnippetTemplate.Cache;
 import com.oracle.graal.snippets.SnippetTemplate.Key;
 import com.oracle.graal.snippets.nodes.*;
-import com.oracle.max.criutils.*;
 
 /**
  * Snippets used for implementing the type test of a checkcast instruction.
@@ -353,7 +352,7 @@
         /**
          * Lowers a checkcast node.
          */
-        public void lower(CheckCastNode checkcast, CiLoweringTool tool) {
+        public void lower(CheckCastNode checkcast, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) checkcast.graph();
             ValueNode hub = checkcast.targetClassInstruction();
             ValueNode object = checkcast.object();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.snippets;
 
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -59,7 +58,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) this.graph();
         IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, false);
         WriteNode write = graph.add(new WriteNode(object, value, location));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java	Tue Jul 03 11:16:56 2012 +0200
@@ -29,14 +29,14 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.util.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 
 public class IntrinsifyArrayCopyPhase extends Phase {
-    private final ExtendedRiRuntime runtime;
+    private final GraalCodeCacheProvider runtime;
     private ResolvedJavaMethod arrayCopy;
     private ResolvedJavaMethod byteArrayCopy;
     private ResolvedJavaMethod shortArrayCopy;
@@ -47,7 +47,7 @@
     private ResolvedJavaMethod doubleArrayCopy;
     private ResolvedJavaMethod objectArrayCopy;
 
-    public IntrinsifyArrayCopyPhase(ExtendedRiRuntime runtime) {
+    public IntrinsifyArrayCopyPhase(GraalCodeCacheProvider runtime) {
         this.runtime = runtime;
         try {
             byteArrayCopy = getArrayCopySnippet(runtime, byte.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java	Tue Jul 03 11:16:56 2012 +0200
@@ -32,7 +32,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
@@ -40,6 +39,7 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
 import com.oracle.graal.snippets.Snippet.Fold;
@@ -176,7 +176,7 @@
          * Lowers a {@link NewInstanceNode}.
          */
         @SuppressWarnings("unused")
-        public void lower(NewInstanceNode newInstanceNode, CiLoweringTool tool) {
+        public void lower(NewInstanceNode newInstanceNode, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) newInstanceNode.graph();
             HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) newInstanceNode.instanceClass();
             HotSpotKlassOop hub = type.klassOop();
@@ -197,7 +197,7 @@
         }
 
         @SuppressWarnings("unused")
-        public void lower(TLABAllocateNode tlabAllocateNode, CiLoweringTool tool) {
+        public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph();
             int size = tlabAllocateNode.size();
             assert (size % wordSize()) == 0;
@@ -210,7 +210,7 @@
         }
 
         @SuppressWarnings("unused")
-        public void lower(InitializeNode initializeNode, CiLoweringTool tool) {
+        public void lower(InitializeNode initializeNode, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) initializeNode.graph();
             HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) initializeNode.type();
             HotSpotKlassOop hub = type.klassOop();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/UnsafeSnippets.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/UnsafeSnippets.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.hotspot.snippets;
 
-import com.oracle.max.cri.util.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.snippets.*;
+import com.oracle.max.criutils.*;
 
 /**
  * Snippets for {@link sun.misc.Unsafe} methods.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java	Tue Jul 03 11:16:56 2012 +0200
@@ -24,48 +24,45 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 
-import java.util.*;
-
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.target.amd64.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
 
 /**
  * LIR instruction for calling HotSpot's {@code new_instance} stub. This stub is declared in c1_Runtime1.hpp
  * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp.
  */
+@Opcode("NEW_INSTANCE")
 public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction {
-    public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRDebugInfo info) {
-        super("NEW_INSTANCE", new Value[] {result}, info, new Value[] {hub}, NO_OPERANDS, new Value[]{AMD64.rax.asValue(Kind.Object)});
+    @Def protected Value result;
+    @Use protected Value hub;
+    @Temp protected Value temp;
+    @State protected LIRFrameState state;
+
+    public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRFrameState state) {
+        this.result = result;
+        this.hub = hub;
+        this.temp = AMD64.rax.asValue(Kind.Object);
+        this.state = state;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        Value result = output(0);
-        Value hub = input(0);
-
         // rdx: (in) hub
         // rax: (out) result
-        assert asRegister(hub) == AMD64.rdx;
-        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, info);
+        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, state);
         if (asRegister(result) != AMD64.rax) {
             masm.movq(asRegister(result), AMD64.rax);
         }
     }
 
     @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        if (mode == OperandMode.Input) {
-            return EnumSet.of(OperandFlag.Register);
-        } else if (mode == OperandMode.Output) {
-            return EnumSet.of(OperandFlag.Register);
-        } else if (mode == OperandMode.Temp) {
-            return EnumSet.of(OperandFlag.Register);
-        }
-        throw GraalInternalError.shouldNotReachHere();
+    protected void verify() {
+        super.verify();
+        assert asRegister(hub) == AMD64.rdx;
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java	Tue Jul 03 11:16:56 2012 +0200
@@ -24,13 +24,10 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.target.amd64.*;
@@ -38,30 +35,26 @@
 /**
  * A call to HotSpot's object pointer verification stub.
  */
+@Opcode("VERIFY_OOP")
 public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction {
-    public AMD64VerifyOopStubCallOp(Value object, LIRDebugInfo info) {
-        super("VERIFY_OOP", LIRInstruction.NO_OPERANDS, info, new Value[] {object}, NO_OPERANDS, NO_OPERANDS);
+    @Use protected Value object;
+    @State protected LIRFrameState state;
+
+    public AMD64VerifyOopStubCallOp(Value object, LIRFrameState state) {
+        this.object = object;
+        this.state = state;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        Register object = asRegister(input(0));
         // r13: (in) object
-        if (object != AMD64.r13) {
+        if (asRegister(object) != AMD64.r13) {
             masm.push(AMD64.r13);
-            masm.movq(AMD64.r13, object);
+            masm.movq(AMD64.r13, asRegister(object));
         }
-        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, info);
-        if (object != AMD64.r13) {
+        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, state);
+        if (asRegister(object) != AMD64.r13) {
             masm.pop(AMD64.r13);
         }
     }
-
-    @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        if (mode == OperandMode.Input) {
-            return EnumSet.of(OperandFlag.Register);
-        }
-        throw GraalInternalError.shouldNotReachHere();
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java	Tue Jul 03 11:16:56 2012 +0200
@@ -25,12 +25,10 @@
 import static com.oracle.graal.hotspot.meta.HotSpotXirGenerator.*;
 import static com.oracle.max.asm.target.amd64.AMD64.*;
 
-import java.util.*;
-
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.target.amd64.*;
@@ -38,12 +36,14 @@
 /**
  * Emits a safepoint poll.
  */
+@Opcode("SAFEPOINT")
 public class AMD64SafepointOp extends AMD64LIRInstruction {
+    @State protected LIRFrameState state;
 
     private final HotSpotVMConfig config;
 
-    public AMD64SafepointOp(LIRDebugInfo info, HotSpotVMConfig config) {
-        super("SAFEPOINT", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+    public AMD64SafepointOp(LIRFrameState state, HotSpotVMConfig config) {
+        this.state = state;
         this.config = config;
     }
 
@@ -54,17 +54,12 @@
         if (config.isPollingPageFar) {
             asm.movq(scratch, config.safepointPollingAddress);
             tasm.recordMark(MARK_POLL_FAR);
-            tasm.recordSafepoint(pos, info);
+            tasm.recordSafepoint(pos, state);
             asm.movq(scratch, new Address(tasm.target.wordKind, scratch.asValue()));
         } else {
             tasm.recordMark(MARK_POLL_NEAR);
-            tasm.recordSafepoint(pos, info);
+            tasm.recordSafepoint(pos, state);
             asm.movq(scratch, new Address(tasm.target.wordKind, rip.asValue()));
         }
     }
-
-    @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        throw GraalInternalError.shouldNotReachHere();
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java	Tue Jul 03 11:16:56 2012 +0200
@@ -26,33 +26,23 @@
 
 import java.util.*;
 
-import com.oracle.max.asm.target.amd64.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
 
 /**
  * Performs a hard-coded tail call to the specified target, which normally should be an RiCompiledCode instance.
  */
+@Opcode("TAILCALL")
 public class AMD64TailcallOp extends AMD64LIRInstruction {
-
-    public AMD64TailcallOp(List<Value> parameters, Value target, Value[] callingConvention) {
-        super("TAILCALL", LIRInstruction.NO_OPERANDS, null, toArray(parameters, target), LIRInstruction.NO_OPERANDS, callingConvention.clone());
-        assert inputs.length == temps.length + 1;
+    @Use protected Value target;
+    @Alive protected Value[] parameters;
 
-        for (int i = 0; i < temps.length; i++) {
-            assert isRegister(temps[i]) : "too many parameters for tail call";
-            assert sameRegister(temps[i], inputs[i]) : "inputs do not match calling convention";
-        }
-    }
-
-    private static Value[] toArray(List<Value> parameters, Value target) {
-        Value[] result = new Value[parameters.size() + 1];
-        parameters.toArray(result);
-        result[parameters.size()] = target;
-        return result;
+    public AMD64TailcallOp(List<Value> parameters, Value target) {
+        this.target = target;
+        this.parameters = parameters.toArray(new Value[parameters.size()]);
     }
 
     @Override
@@ -61,17 +51,7 @@
         masm.leave();
 
         // jump to the target method
-        masm.jmp(asRegister(inputs[inputs.length - 1]));
+        masm.jmp(asRegister(target));
         masm.ensureUniquePC();
     }
-
-    @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        if (mode == OperandMode.Input) {
-            return EnumSet.of(OperandFlag.Register);
-        } else if (mode == OperandMode.Temp) {
-            return EnumSet.of(OperandFlag.Register);
-        }
-        throw GraalInternalError.shouldNotReachHere();
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Tue Jul 03 11:16:56 2012 +0200
@@ -61,7 +61,7 @@
 
             @Override
             public void visitSafepointNode(SafepointNode i) {
-                LIRDebugInfo info = state();
+                LIRFrameState info = state();
                 append(new AMD64SafepointOp(info, ((HotSpotRuntime) runtime).config));
             }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.interpreter/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.interpreter</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.java</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Tue Jul 03 11:16:56 2012 +0200
@@ -404,10 +404,15 @@
     }
 
     private void addSwitchSuccessors(int predBci, BytecodeSwitch bswitch) {
+        // adds distinct targets to the successor list
+        Collection<Integer> targets = new TreeSet<>();
         for (int i = 0; i < bswitch.numberOfCases(); i++) {
-            addSuccessor(predBci, makeBlock(bswitch.targetAt(i)));
+            targets.add(bswitch.targetAt(i));
         }
-        addSuccessor(predBci, makeBlock(bswitch.defaultTarget()));
+        targets.add(bswitch.defaultTarget());
+        for (int targetBci : targets) {
+            addSuccessor(predBci, makeBlock(targetBci));
+        }
     }
 
     private void addSuccessor(int predBci, Block sux) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Tue Jul 03 11:16:56 2012 +0200
@@ -317,7 +317,7 @@
     }
 
     /**
-     * Stores a given local variable at the specified index. If the value is a {@linkplain Kind#isDoubleWord() double word},
+     * Stores a given local variable at the specified index. If the value occupies {@linkplain FrameStateBuilder#isTwoSlot(Kind) two slots},
      * then the next local variable index is also overwritten.
      *
      * @param i the index at which to store
@@ -498,7 +498,6 @@
 
     /**
      * Pop the specified number of slots off of this stack and return them as an array of instructions.
-     * @param size the number of arguments off of the stack
      * @return an array containing the arguments off of the stack
      */
     public ValueNode[] popArguments(int slotSize, int argSize) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Jul 03 11:16:56 2012 +0200
@@ -130,13 +130,13 @@
 
     @Override
     protected String getDetailedName() {
-        return getName() + " " + CodeUtil.format("%H.%n(%p):%r", method);
+        return getName() + " " + MetaUtil.format("%H.%n(%p):%r", method);
     }
 
     private BciBlockMapping createBlockMap() {
         BciBlockMapping map = new BciBlockMapping(method);
         map.build();
-        Debug.dump(map, CodeUtil.format("After block building %f %R %H.%n(%P)", method));
+        Debug.dump(map, MetaUtil.format("After block building %f %R %H.%n(%P)", method));
 
         return map;
     }
@@ -149,7 +149,7 @@
 
         if (GraalOptions.PrintProfilingInformation) {
             TTY.println("Profiling info for " + method);
-            TTY.println(CodeUtil.indent(CodeUtil.profileToString(profilingInfo, method, CodeUtil.NEW_LINE), "  "));
+            TTY.println(MetaUtil.indent(MetaUtil.profileToString(profilingInfo, method, CodeUtil.NEW_LINE), "  "));
         }
 
         // compute the block map, setup exception handlers and get the entrypoint(s)
@@ -283,9 +283,9 @@
 
         if (con instanceof JavaType) {
             // this is a load of class constant which might be unresolved
-            JavaType riType = (JavaType) con;
-            if (riType instanceof ResolvedJavaType) {
-                frameState.push(Kind.Object, append(ConstantNode.forConstant(((ResolvedJavaType) riType).getEncoding(Representation.JavaClass), runtime, currentGraph)));
+            JavaType type = (JavaType) con;
+            if (type instanceof ResolvedJavaType) {
+                frameState.push(Kind.Object, append(ConstantNode.forConstant(((ResolvedJavaType) type).getEncoding(Representation.JavaClass), runtime, currentGraph)));
             } else {
                 append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved, graphId)));
                 frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph)));
@@ -541,7 +541,7 @@
         BeginNode trueSuccessor = createBlockTarget(probability, trueBlock, frameState);
         BeginNode falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState);
 
-        IfNode ifNode = negate ? new IfNode(condition, falseSuccessor, trueSuccessor, 1 - probability) : new IfNode(condition, trueSuccessor, falseSuccessor, probability);
+        IfNode ifNode = negate ? new IfNode(condition, falseSuccessor, trueSuccessor, 1 - probability, graphId) : new IfNode(condition, trueSuccessor, falseSuccessor, probability, graphId);
         append(currentGraph.add(ifNode));
     }
 
@@ -653,7 +653,7 @@
         } else {
             BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode());
             DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved, graphId));
-            IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 0));
+            IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1, graphId));
             append(ifNode);
             lastInstr = successor;
             frameState.ipush(appendConstant(Constant.INT_0));
@@ -757,7 +757,7 @@
     private void emitNullCheck(ValueNode receiver) {
         BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode());
         BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode());
-        IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 1));
+        IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.5, graphId));
 
         append(ifNode);
         lastInstr = falseSucc;
@@ -776,7 +776,7 @@
     private void emitBoundsCheck(ValueNode index, ValueNode length) {
         BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode());
         BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode());
-        IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 1));
+        IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 0.5, graphId));
 
         append(ifNode);
         lastInstr = trueSucc;
@@ -1041,22 +1041,6 @@
         appendGoto(createTarget(successor, frameState));
     }
 
-    private void genTableswitch() {
-        int bci = bci();
-        ValueNode value = frameState.ipop();
-        BytecodeTableSwitch ts = new BytecodeTableSwitch(stream(), bci);
-
-        int nofCases = ts.numberOfCases() + 1; // including default case
-        assert currentBlock.numNormalSuccessors() == nofCases;
-
-        double[] probabilities = switchProbability(nofCases, bci);
-        TableSwitchNode tableSwitch = currentGraph.add(new TableSwitchNode(value, ts.lowKey(), probabilities));
-        for (int i = 0; i < nofCases; ++i) {
-            tableSwitch.setBlockSuccessor(i, createBlockTarget(probabilities[i], currentBlock.successors.get(i), frameState));
-        }
-        append(tableSwitch);
-    }
-
     private double[] switchProbability(int numberOfCases, int bci) {
         double[] prob = profilingInfo.getSwitchProbabilities(bci);
         if (prob != null) {
@@ -1081,22 +1065,35 @@
         return true;
     }
 
-    private void genLookupswitch() {
+    private void genSwitch(BytecodeSwitch bs) {
         int bci = bci();
         ValueNode value = frameState.ipop();
-        BytecodeLookupSwitch ls = new BytecodeLookupSwitch(stream(), bci);
+
+        int nofCases = bs.numberOfCases();
 
-        int nofCases = ls.numberOfCases() + 1; // including default case
-        assert currentBlock.numNormalSuccessors() == nofCases;
+        Map<Integer, Integer> bciToSuccessorIndex = new HashMap<>();
+        int successorCount = currentBlock.successors.size();
+        for (int i = 0; i < successorCount; i++) {
+            assert !bciToSuccessorIndex.containsKey(currentBlock.successors.get(i).startBci);
+            if (!bciToSuccessorIndex.containsKey(currentBlock.successors.get(i).startBci)) {
+                bciToSuccessorIndex.put(currentBlock.successors.get(i).startBci, i);
+            }
+        }
 
-        int[] keys = new int[nofCases - 1];
-        for (int i = 0; i < nofCases - 1; ++i) {
-            keys[i] = ls.keyAt(i);
+        double[] keyProbabilities = switchProbability(nofCases + 1, bci);
+
+        int[] keys = new int[nofCases];
+        int[] keySuccessors = new int[nofCases + 1];
+        for (int i = 0; i < nofCases; i++) {
+            keys[i] = bs.keyAt(i);
+            keySuccessors[i] = bciToSuccessorIndex.get(bs.targetAt(i));
         }
-        double[] probabilities = switchProbability(nofCases, bci);
-        LookupSwitchNode lookupSwitch = currentGraph.add(new LookupSwitchNode(value, keys, probabilities));
-        for (int i = 0; i < nofCases; ++i) {
-            lookupSwitch.setBlockSuccessor(i, createBlockTarget(probabilities[i], currentBlock.successors.get(i), frameState));
+        keySuccessors[nofCases] = bciToSuccessorIndex.get(bs.defaultTarget());
+
+        double[] successorProbabilities = IntegerSwitchNode.successorProbabilites(successorCount, keySuccessors, keyProbabilities);
+        IntegerSwitchNode lookupSwitch = currentGraph.add(new IntegerSwitchNode(value, successorCount, keys, keyProbabilities, keySuccessors));
+        for (int i = 0; i < successorCount; i++) {
+            lookupSwitch.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], currentBlock.successors.get(i), frameState));
         }
         append(lookupSwitch);
     }
@@ -1409,7 +1406,7 @@
             frameState.push(Kind.Object, exception);
             FixedNode nextDispatch = createTarget(nextBlock, frameState);
             checkCast.setNext(catchSuccessor);
-            IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new InstanceOfNode(typeInstruction, (ResolvedJavaType) catchType, exception)), checkCast, nextDispatch, 0.5));
+            IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new InstanceOfNode(typeInstruction, (ResolvedJavaType) catchType, exception)), checkCast, nextDispatch, 0.5, graphId));
             append(ifNode);
         }
     }
@@ -1695,8 +1692,8 @@
             case GOTO           : genGoto(); break;
             case JSR            : genJsr(stream.readBranchDest()); break;
             case RET            : genRet(stream.readLocalIndex()); break;
-            case TABLESWITCH    : genTableswitch(); break;
-            case LOOKUPSWITCH   : genLookupswitch(); break;
+            case TABLESWITCH    : genSwitch(new BytecodeTableSwitch(stream(), bci())); break;
+            case LOOKUPSWITCH   : genSwitch(new BytecodeLookupSwitch(stream(), bci())); break;
             case IRETURN        : genReturn(frameState.ipop()); break;
             case LRETURN        : genReturn(frameState.lpop()); break;
             case FRETURN        : genReturn(frameState.fpop()); break;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.jtt</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_ldiv3.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,54 @@
+/*
+ * 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.graal.jtt.bytecode;
+
+import org.junit.*;
+
+/*
+ */
+public class BC_ldiv3 {
+    public static long PLUS7 = 7;
+    public static long PLUS3 = 3;
+    public static long MIN7 = -7;
+    public static long MIN3 = -3;
+
+    public static long test(long a, long b) {
+        return a / b;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertEquals(3, test(PLUS7, 2));
+        Assert.assertEquals(1, test(PLUS3, 2));
+        Assert.assertEquals(-3, test(MIN7, 2));
+        Assert.assertEquals(-1, test(MIN3, 2));
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        Assert.assertEquals(-1, test(PLUS7, -4));
+        Assert.assertEquals(0, test(PLUS3, -4));
+        Assert.assertEquals(1, test(MIN7, -4));
+        Assert.assertEquals(0, test(MIN3, -4));
+    }
+}
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6959129.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6959129.java	Tue Jul 03 11:16:56 2012 +0200
@@ -28,12 +28,11 @@
  * @test
  * @bug 6959129
  * @summary COMPARISON WITH INTEGER.MAX_INT DOES NOT WORK CORRECTLY IN THE CLIENT VM.
- * 
+ *
  *          This test will not run properly without assertions
- * 
+ *
  * @run main/othervm -ea Test6959129
  */
-
 public class Test6959129 {
 
     public static int test() {
@@ -71,7 +70,7 @@
 
     /**
      * Returns the maximum length of the hailstone sequence for numbers between min to max.
-     * 
+     *
      * For rec1 - Assume that min is bigger than max.
      */
     public static long maxMoves(int min, int max) {
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test7005594.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test7005594.java	Tue Jul 03 11:16:56 2012 +0200
@@ -26,11 +26,9 @@
  * @test
  * @bug 7005594
  * @summary Array overflow not handled correctly with loop optimzations
- * 
+ *
  * @run shell Test7005594.sh
- * @##Disabled huge heap##Runs: 0 = 95
  */
-
 public class Test7005594 {
 
     private static int test0(byte[] a) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.amd64/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.lir.amd64</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,16 +23,15 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-
-import java.util.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import com.oracle.max.asm.*;
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
 
 public enum AMD64Arithmetic {
     IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
@@ -48,254 +47,183 @@
 
 
     public static class Op1Reg extends AMD64LIRInstruction {
-        public Op1Reg(AMD64Arithmetic opcode, Value result, Value x) {
-            super(opcode, new Value[] {result}, null, new Value[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value x = input(0);
-
-            emit(tasm, masm, (AMD64Arithmetic) code, result, x, null);
-        }
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG}) protected Value x;
 
-        @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, Value result, Value x) {
-            super(opcode, new Value[] {result}, null, new Value[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        public Op1Reg(AMD64Arithmetic opcode, Value result, Value x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value 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();
+            emit(tasm, masm, opcode, result, x, null);
         }
     }
 
-    public static class Op2Stack extends AMD64LIRInstruction {
-        public Op2Stack(AMD64Arithmetic opcode, Value result, Value x, Value y) {
-            super(opcode, new Value[] {result}, null, new Value[] {x}, new Value[] {y}, LIRInstruction.NO_OPERANDS);
+    public static class Op1Stack extends AMD64LIRInstruction {
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+
+        public Op1Stack(AMD64Arithmetic opcode, Value result, Value x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value x = input(0);
-            Value 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() {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = alive(0);
-
-            super.verify();
-            assert differentRegisters(result, y) || sameRegister(x, y);
-            verifyKind((AMD64Arithmetic) code, result, x, y);
+            emit(tasm, masm, opcode, result);
         }
     }
 
-    public static class Op2Reg extends AMD64LIRInstruction {
-        public Op2Reg(AMD64Arithmetic opcode, Value result, Value x, Value y) {
-            super(opcode, new Value[] {result}, null, new Value[] {x}, new Value[] {y}, LIRInstruction.NO_OPERANDS);
+    public static class Op2Stack extends AMD64LIRInstruction {
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Alive({REG, STACK, CONST}) protected Value y;
+
+        public Op2Stack(AMD64Arithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value x = input(0);
-            Value 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();
+            emit(tasm, masm, opcode, result, y, null);
         }
 
         @Override
         public void verify() {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = alive(0);
-
             super.verify();
             assert differentRegisters(result, y) || sameRegister(x, y);
-            verifyKind((AMD64Arithmetic) code, result, x, y);
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+    public static class Op2Reg extends AMD64LIRInstruction {
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Alive({REG, CONST}) protected Value y;
+
+        public Op2Reg(AMD64Arithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            AMD64Move.move(tasm, masm, result, x);
+            emit(tasm, masm, opcode, result, y, null);
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            assert differentRegisters(result, y) || sameRegister(x, y);
+            verifyKind(opcode, result, x, y);
         }
     }
 
     public static class Op2RegCommutative extends AMD64LIRInstruction {
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Use({REG, CONST}) protected Value y;
+
         public Op2RegCommutative(AMD64Arithmetic opcode, Value result, Value x, Value y) {
-            super(opcode, new Value[] {result}, null, new Value[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = input(1);
-
             if (sameRegister(result, y)) {
-                emit(tasm, masm, (AMD64Arithmetic) code, result, x, null);
+                emit(tasm, masm, opcode, result, x, null);
             } else {
                 AMD64Move.move(tasm, masm, result, x);
-                emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
+                emit(tasm, masm, opcode, 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() {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = input(1);
-
             super.verify();
-            verifyKind((AMD64Arithmetic) code, result, x, y);
+            verifyKind(opcode, result, x, y);
         }
     }
 
     public static class ShiftOp extends AMD64LIRInstruction {
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Alive({REG, CONST}) protected Value y;
+
         public ShiftOp(AMD64Arithmetic opcode, Value result, Value x, Value y) {
-            super(opcode, new Value[] {result}, null, new Value[] {x}, new Value[] {y}, LIRInstruction.NO_OPERANDS);
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value x = input(0);
-            Value 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();
+            emit(tasm, masm, opcode, result, y, null);
         }
 
         @Override
         public void verify() {
-            Value result = output(0);
-            Value x = input(0);
-            Value 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);
+            verifyKind(opcode, result, x, x);
             assert y.kind.stackKind() == Kind.Int;
         }
     }
 
     public static class DivOp extends AMD64LIRInstruction {
-        public DivOp(AMD64Arithmetic opcode, Value result, Value x, Value y, LIRDebugInfo info) {
-            super(opcode, new Value[] {result}, info, new Value[] {x}, new Value[] {y}, new Value[] {asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind)});
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def protected Value result;
+        @Use protected Value x;
+        @Alive protected Value y;
+        @Temp protected Value temp;
+        @State protected LIRFrameState state;
+
+        public DivOp(AMD64Arithmetic opcode, Value result, Value x, Value y, LIRFrameState state) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+            this.temp = asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind);
+            this.state = state;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value 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();
+            emit(tasm, masm, opcode, result, y, state);
         }
 
         @Override
         protected void verify() {
-            Value result = output(0);
-            Value x = input(0);
-            Value 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);
+            verifyKind(opcode, result, x, y);
         }
     }
 
@@ -313,7 +241,7 @@
         }
     }
 
-    public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, Value dst, Value src, LIRDebugInfo info) {
+    public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, Value dst, Value src, LIRFrameState info) {
         int exceptionOffset = -1;
         if (isRegister(src)) {
             switch (opcode) {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,27 +23,35 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import java.util.*;
 
+import com.oracle.graal.api.code.CompilationResult.Mark;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CompilationResult.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.asm.*;
 
 public class AMD64Call {
 
+    @Opcode("CALL_DIRECT")
     public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
-        private final Object targetMethod;
-        private final Map<XirMark, Mark> marks;
+        @Def({REG, ILLEGAL}) protected Value result;
+        @Use({REG, STACK}) protected Value[] parameters;
+        @State protected LIRFrameState state;
 
-        public DirectCallOp(Object targetMethod, Value result, Value[] parameters, LIRDebugInfo info, Map<XirMark, Mark> marks) {
-            super("CALL_DIRECT", new Value[] {result}, info, parameters, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        protected final Object targetMethod;
+        protected final Map<XirMark, Mark> marks;
+
+        public DirectCallOp(Object targetMethod, Value result, Value[] parameters, LIRFrameState state, Map<XirMark, Mark> marks) {
             this.targetMethod = targetMethod;
+            this.result = result;
+            this.parameters = parameters;
+            this.state = state;
             this.marks = marks;
         }
 
@@ -53,57 +61,36 @@
             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();
+            directCall(tasm, masm, targetMethod, state);
         }
     }
 
+    @Opcode("CALL_INDIRECT")
     public static class IndirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+        @Def({REG, ILLEGAL}) protected Value result;
+        @Use({REG, STACK}) protected Value[] parameters;
+        @Use({REG}) protected Value targetAddress;
+        @State protected LIRFrameState state;
+
         private final Object targetMethod;
         private final Map<XirMark, Mark> marks;
 
-        private static Value[] concat(Value[] parameters, Value targetAddress) {
-            Value[] result = Arrays.copyOf(parameters, parameters.length + 1);
-            result[result.length - 1] = targetAddress;
-            return result;
-        }
-
-        public IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value targetAddress, LIRDebugInfo info, Map<XirMark, Mark> marks) {
-            super("CALL_INDIRECT", new Value[] {result}, info, concat(parameters, targetAddress), LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        public IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value targetAddress, LIRFrameState state, Map<XirMark, Mark> marks) {
             this.targetMethod = targetMethod;
+            this.result = result;
+            this.parameters = parameters;
+            this.targetAddress = targetAddress;
+            this.state = state;
             this.marks = marks;
         }
 
-        private Value 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();
+            indirectCall(tasm, masm, asRegister(targetAddress), targetMethod, state);
         }
     }
 
@@ -117,7 +104,7 @@
         }
     }
 
-    public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRDebugInfo info) {
+    public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRFrameState info) {
         int before = masm.codeBuffer.position();
         if (target instanceof RuntimeCall) {
             long maxOffset = tasm.runtime.getMaxCallTargetOffset((RuntimeCall) target);
@@ -148,7 +135,7 @@
         masm.ensureUniquePC();
     }
 
-    public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, Object target, LIRDebugInfo info) {
+    public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, Object target, LIRFrameState info) {
         int before = masm.codeBuffer.position();
         masm.call(dst);
         int after = masm.codeBuffer.position();
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,45 +23,34 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import java.util.*;
-
-import com.oracle.max.asm.target.amd64.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
 
 public enum AMD64Compare {
     ICMP, LCMP, ACMP, FCMP, DCMP;
 
     public static class CompareOp extends AMD64LIRInstruction {
+        @Opcode private final AMD64Compare opcode;
+        @Use({REG}) protected Value x;
+        @Use({REG, STACK, CONST}) protected Value y;
+
         public CompareOp(AMD64Compare opcode, Value x, Value y) {
-            super(opcode, LIRInstruction.NO_OPERANDS, null, new Value[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.opcode = opcode;
+            this.x = x;
+            this.y = y;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value x = input(0);
-            Value 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();
+            emit(tasm, masm, opcode, x, y);
         }
 
         @Override
         protected void verify() {
-            Value x = input(0);
-            Value y = input(1);
-
             super.verify();
             assert (name().startsWith("I") && x.kind == Kind.Int && y.kind.stackKind() == Kind.Int)
                 || (name().startsWith("I") && x.kind == Kind.Jsr && y.kind == Kind.Jsr)
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,26 +23,29 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import java.util.*;
-
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.Address.Scale;
+import com.oracle.graal.api.code.CompilationResult.JumpTable;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.StandardOp.FallThroughOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.max.asm.*;
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.Address.*;
-import com.oracle.graal.api.code.CompilationResult.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 public class AMD64ControlFlow {
 
     public static class ReturnOp extends AMD64LIRInstruction {
-        public ReturnOp(Value input) {
-            super("RETURN", LIRInstruction.NO_OPERANDS, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        @Use({REG, ILLEGAL}) protected Value x;
+
+        public ReturnOp(Value x) {
+            this.x = x;
         }
 
         @Override
@@ -52,29 +55,22 @@
             }
             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 ConditionFlag condition;
         protected LabelRef destination;
+        @State protected LIRFrameState state;
 
-        public BranchOp(Condition condition, LabelRef destination, LIRDebugInfo info) {
+        public BranchOp(Condition condition, LabelRef destination, LIRFrameState info) {
             this(intCond(condition), destination, info);
         }
 
-        public BranchOp(ConditionFlag condition, LabelRef destination, LIRDebugInfo info) {
-            super("BRANCH", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        public BranchOp(ConditionFlag condition, LabelRef destination, LIRFrameState state) {
             this.condition = condition;
             this.destination = destination;
+            this.state = state;
         }
 
         @Override
@@ -92,23 +88,13 @@
             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) {
+        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination, LIRFrameState info) {
             super(floatCond(condition), destination, info);
             this.unorderedIsTrue = unorderedIsTrue;
         }
@@ -123,11 +109,6 @@
             super.negate(newDestination);
             unorderedIsTrue = !unorderedIsTrue;
         }
-
-        @Override
-        public String operationString() {
-            return condition.operator + " [" + destination + "]" + (unorderedIsTrue ? " unorderedIsTrue" : " unorderedIsFalse");
-        }
     }
 
 
@@ -135,109 +116,183 @@
         private final int lowKey;
         private final LabelRef defaultTarget;
         private final LabelRef[] targets;
+        @Alive protected Value index;
+        @Temp protected Value scratch;
 
         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 Value[] {index}, new Value[] {scratch});
             this.lowKey = lowKey;
             this.defaultTarget = defaultTarget;
             this.targets = targets;
+            this.index = index;
+            this.scratch = scratch;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch));
+        }
+    }
+
+    public static class SequentialSwitchOp extends AMD64LIRInstruction implements FallThroughOp {
+        @Use({CONST}) protected Constant[] keyConstants;
+        private final LabelRef[] keyTargets;
+        private LabelRef defaultTarget;
+        @Alive({REG}) protected Value key;
+        @Temp({REG, ILLEGAL}) protected Value scratch;
+
+        public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
+            assert keyConstants.length == keyTargets.length;
+            this.keyConstants = keyConstants;
+            this.keyTargets = keyTargets;
+            this.defaultTarget = defaultTarget;
+            this.key = key;
+            this.scratch = scratch;
         }
 
         @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++;
+            if (key.kind == Kind.Int) {
+                Register intKey = asIntReg(key);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    masm.cmpl(intKey, tasm.asIntConst(keyConstants[i]));
+                    masm.jcc(ConditionFlag.equal, keyTargets[i].label());
+                }
+            } else if (key.kind == Kind.Object) {
+                Register intKey = asObjectReg(key);
+                Register temp = asObjectReg(scratch);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    AMD64Move.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]);
+                    masm.cmpptr(intKey, temp);
+                    masm.jcc(ConditionFlag.equal, keyTargets[i].label());
+                }
+            } else {
+                throw new GraalInternalError("sequential switch only supported for int and object");
             }
-            return buf.toString();
+            if (defaultTarget != null) {
+                masm.jmp(defaultTarget.label());
+            } else {
+                masm.hlt();
+            }
         }
 
         @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 LabelRef fallThroughTarget() {
+            return defaultTarget;
+        }
+
+        @Override
+        public void setFallThroughTarget(LabelRef target) {
+            defaultTarget = target;
         }
     }
 
-
-    public static class CondMoveOp extends AMD64LIRInstruction {
-        private final ConditionFlag condition;
+    public static class SwitchRangesOp extends AMD64LIRInstruction implements FallThroughOp {
+        private final LabelRef[] keyTargets;
+        private LabelRef defaultTarget;
+        private final int[] lowKeys;
+        private final int[] highKeys;
+        @Alive protected Value key;
 
-        public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
-            super("CMOVE", new Value[] {result}, null, new Value[] {falseValue}, new Value[] {trueValue}, LIRInstruction.NO_OPERANDS);
-            this.condition = intCond(condition);
+        public SwitchRangesOp(int[] lowKeys, int[] highKeys, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
+            this.lowKeys = lowKeys;
+            this.highKeys = highKeys;
+            this.keyTargets = keyTargets;
+            this.defaultTarget = defaultTarget;
+            this.key = key;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            cmove(tasm, masm, output(0), false, condition, false, alive(0), input(0));
+            for (int i = 0; i < lowKeys.length; i++) {
+                int lowKey = lowKeys[i];
+                int highKey = highKeys[i];
+                if (lowKey == highKey) {
+                    masm.cmpl(asIntReg(key), lowKey);
+                    masm.jcc(ConditionFlag.equal, keyTargets[i].label());
+                } else if (lowKey + 1 == highKey) {
+                    masm.cmpl(asIntReg(key), lowKey);
+                    masm.jcc(ConditionFlag.equal, keyTargets[i].label());
+                    masm.cmpl(asIntReg(key), highKey);
+                    masm.jcc(ConditionFlag.equal, keyTargets[i].label());
+                } else {
+                    Label skip = new Label();
+                    masm.cmpl(asIntReg(key), lowKey);
+                    masm.jcc(ConditionFlag.less, skip);
+                    masm.cmpl(asIntReg(key), highKey);
+                    masm.jcc(ConditionFlag.lessEqual, keyTargets[i].label());
+                    masm.bind(skip);
+                }
+            }
+            if (defaultTarget != null) {
+                masm.jmp(defaultTarget.label());
+            } else {
+                masm.hlt();
+            }
         }
 
         @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();
+        protected void verify() {
+            super.verify();
+            assert lowKeys.length == keyTargets.length;
+            assert highKeys.length == keyTargets.length;
+            assert key.kind == Kind.Int;
         }
 
         @Override
-        public String operationString() {
-            return condition.toString() + " " + super.operationString();
+        public LabelRef fallThroughTarget() {
+            return defaultTarget;
+        }
+
+        @Override
+        public void setFallThroughTarget(LabelRef target) {
+            defaultTarget = target;
         }
     }
 
 
+    @Opcode("CMOVE")
+    public static class CondMoveOp extends AMD64LIRInstruction {
+        @Def({REG, HINT}) protected Value result;
+        @Alive({REG}) protected Value trueValue;
+        @Use({REG, STACK, CONST}) protected Value falseValue;
+        private final ConditionFlag condition;
+
+        public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
+            this.result = result;
+            this.condition = intCond(condition);
+            this.trueValue = trueValue;
+            this.falseValue = falseValue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            cmove(tasm, masm, result, false, condition, false, trueValue, falseValue);
+        }
+    }
+
+
+    @Opcode("CMOVE")
     public static class FloatCondMoveOp extends AMD64LIRInstruction {
+        @Def({REG}) protected Value result;
+        @Alive({REG}) protected Value trueValue;
+        @Alive({REG}) protected Value falseValue;
         private final ConditionFlag condition;
         private final boolean unorderedIsTrue;
 
         public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
-            super("FLOAT_CMOVE", new Value[] {result}, null, LIRInstruction.NO_OPERANDS, new Value[] {trueValue, falseValue}, LIRInstruction.NO_OPERANDS);
+            this.result = result;
             this.condition = floatCond(condition);
             this.unorderedIsTrue = unorderedIsTrue;
+            this.trueValue = trueValue;
+            this.falseValue = falseValue;
         }
 
         @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();
+            cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue);
         }
     }
 
-
     private static void tableswitch(TargetMethodAssembler tasm, AMD64MacroAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, Register value, Register scratch) {
         Buffer buf = masm.codeBuffer;
         // Compare index against jump table bounds
@@ -251,7 +306,9 @@
         }
 
         // Jump to default target if index is not within the jump table
-        masm.jcc(ConditionFlag.above, defaultTarget.label());
+        if (defaultTarget != null) {
+            masm.jcc(ConditionFlag.above, defaultTarget.label());
+        }
 
         // Set scratch to address of jump table
         int leaPos = buf.position();
@@ -284,7 +341,7 @@
             } else {
                 label.addPatchAt(buf.position());
 
-                buf.emitByte(0); // psuedo-opcode for jump table entry
+                buf.emitByte(0); // pseudo-opcode for jump table entry
                 buf.emitShort(offsetToJumpTableBase);
                 buf.emitByte(0); // padding to make jump table entry 4 bytes wide
             }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,20 +22,14 @@
  */
 package com.oracle.graal.lir.amd64;
 
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
 
 /**
  * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method.
  */
 public abstract class AMD64LIRInstruction extends LIRInstruction {
-
-    public AMD64LIRInstruction(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps) {
-        super(opcode, outputs, info, inputs, alives, temps);
-    }
-
     @Override
     public final void emitCode(TargetMethodAssembler tasm) {
         emitCode(tasm, (AMD64MacroAssembler) tasm.asm);
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,25 +23,30 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 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.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
 
 public class AMD64Move {
 
+    @Opcode("MOVE")
     public static class SpillMoveOp extends AMD64LIRInstruction implements MoveOp {
+        @Def({REG, STACK}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value input;
+
         public SpillMoveOp(Value result, Value input) {
-            super("MOVE", new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.result = result;
+            this.input = input;
         }
 
         @Override
@@ -51,28 +56,23 @@
 
         @Override
         public Value getInput() {
-            return input(0);
+            return input;
         }
         @Override
         public Value 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();
+            return result;
         }
     }
 
 
+    @Opcode("MOVE")
     public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp {
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value input;
+
         public MoveToRegOp(Value result, Value input) {
-            super("MOVE", new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.result = result;
+            this.input = input;
         }
 
         @Override
@@ -82,28 +82,23 @@
 
         @Override
         public Value getInput() {
-            return input(0);
+            return input;
         }
         @Override
         public Value 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();
+            return result;
         }
     }
 
 
+    @Opcode("MOVE")
     public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp {
+        @Def({REG, STACK}) protected Value result;
+        @Use({REG, CONST, HINT}) protected Value input;
+
         public MoveFromRegOp(Value result, Value input) {
-            super("MOVE", new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.result = result;
+            this.input = input;
         }
 
         @Override
@@ -113,87 +108,63 @@
 
         @Override
         public Value getInput() {
-            return input(0);
+            return input;
         }
         @Override
         public Value 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();
+            return result;
         }
     }
 
 
     public static class LoadOp extends AMD64LIRInstruction {
-        public LoadOp(Value result, Value address, LIRDebugInfo info) {
-            super("LOAD", new Value[] {result}, info, new Value[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        @Def({REG}) protected Value result;
+        @Use({ADDR}) protected Value address;
+        @State protected LIRFrameState state;
+
+        public LoadOp(Value result, Value address, LIRFrameState state) {
+            this.result = result;
+            this.address = address;
+            this.state = state;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            load(tasm, masm, output(0), (Address) 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();
+            load(tasm, masm, result, (Address) address, state);
         }
     }
 
 
     public static class StoreOp extends AMD64LIRInstruction {
-        public StoreOp(Value address, Value input, LIRDebugInfo info) {
-            super("STORE", LIRInstruction.NO_OPERANDS, info, new Value[] {address, input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        @Use({ADDR}) protected Value address;
+        @Use({REG, CONST}) protected Value input;
+        @State protected LIRFrameState state;
+
+        public StoreOp(Value address, Value input, LIRFrameState state) {
+            this.address = address;
+            this.input = input;
+            this.state = state;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            store(tasm, masm, (Address) 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();
+            store(tasm, masm, (Address) address, input, state);
         }
     }
 
 
     public static class LeaOp extends AMD64LIRInstruction {
+        @Def({REG}) protected Value result;
+        @Use({ADDR, STACK, UNINITIALIZED}) protected Value address;
+
         public LeaOp(Value result, Value address) {
-            super("LEA", new Value[] {result}, null, new Value[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.result = result;
+            this.address = address;
         }
 
         @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();
+            masm.leaq(asLongReg(result), tasm.asAddress(address));
         }
     }
 
@@ -202,7 +173,6 @@
         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;
         }
 
@@ -210,57 +180,43 @@
         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 Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        @Use protected Value input;
+        @State protected LIRFrameState state;
+
+        public NullCheckOp(Variable input, LIRFrameState state) {
+            this.input = input;
+            this.state = state;
         }
 
         @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();
+            tasm.recordImplicitException(masm.codeBuffer.position(), state);
+            masm.nullCheck(asRegister(input));
         }
     }
 
 
+    @Opcode("CAS")
     public static class CompareAndSwapOp extends AMD64LIRInstruction {
+        @Def protected Value result;
+        @Use({ADDR}) protected Value address;
+        @Use protected Value cmpValue;
+        @Use protected Value newValue;
+
         public CompareAndSwapOp(Value result, Address address, Value cmpValue, Value newValue) {
-            super("CAS", new Value[] {result}, null, new Value[] {address, cmpValue, newValue}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.result = result;
+            this.address = address;
+            this.cmpValue = cmpValue;
+            this.newValue = newValue;
         }
 
         @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();
+            compareAndSwap(tasm, masm, result, (Address) address, cmpValue, newValue);
         }
     }
 
@@ -404,7 +360,7 @@
     }
 
 
-    public static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Address loadAddr, LIRDebugInfo info) {
+    public static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Address loadAddr, LIRFrameState info) {
         if (info != null) {
             tasm.recordImplicitException(masm.codeBuffer.position(), info);
         }
@@ -422,7 +378,7 @@
         }
     }
 
-    public static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Address storeAddr, Value input, LIRDebugInfo info) {
+    public static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Address storeAddr, Value input, LIRFrameState info) {
         if (info != null) {
             tasm.recordImplicitException(masm.codeBuffer.position(), info);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.lir</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Tue Jul 03 11:16:56 2012 +0200
@@ -85,8 +85,6 @@
 
     /**
      * Creates a new LIR instance for the specified compilation.
-     * @param numLoops number of loops
-     * @param compilation the compilation
      */
     public LIR(ControlFlowGraph cfg, BlockMap<List<ScheduledNode>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder) {
         this.cfg = cfg;
@@ -110,7 +108,7 @@
     public boolean hasDebugInfo() {
         for (Block b : linearScanOrder()) {
             for (LIRInstruction op : b.lir) {
-                if (op.info != null) {
+                if (op.hasState()) {
                     return true;
                 }
             }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRDebugInfo.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +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.graal.lir;
-
-import static com.oracle.graal.api.code.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.lir.LIRInstruction.OperandFlag;
-import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
-
-/**
- * This class represents garbage collection and deoptimization information attached to a LIR instruction.
- */
-public class LIRDebugInfo {
-    public final BytecodeFrame topFrame;
-    private final VirtualObject[] virtualObjects;
-    private final List<StackSlot> pointerSlots;
-    public final LabelRef exceptionEdge;
-    private DebugInfo debugInfo;
-
-    public LIRDebugInfo(BytecodeFrame topFrame, VirtualObject[] virtualObjects, List<StackSlot> pointerSlots, LabelRef exceptionEdge) {
-        this.topFrame = topFrame;
-        this.virtualObjects = virtualObjects;
-        this.pointerSlots = pointerSlots;
-        this.exceptionEdge = exceptionEdge;
-    }
-
-    public boolean hasDebugInfo() {
-        return debugInfo != null;
-    }
-
-    public DebugInfo 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 (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) {
-            processValues(cur.values, proc);
-        }
-        if (virtualObjects != null) {
-            for (VirtualObject 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(Value[] values, ValueProcedure proc) {
-        for (int i = 0; i < values.length; i++) {
-            Value value = values[i];
-            if (value instanceof MonitorValue) {
-                MonitorValue monitor = (MonitorValue) value;
-                if (processed(monitor.getOwner())) {
-                    monitor.setOwner(proc.doValue(monitor.getOwner(), OperandMode.Alive, STATE_FLAGS));
-                }
-
-            } else if (processed(value)) {
-                values[i] = proc.doValue(value, OperandMode.Alive, STATE_FLAGS);
-            }
-        }
-    }
-
-    private boolean processed(Value 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(BitSet registerRefMap, BitSet frameRefMap, FrameMap frameMap) {
-        debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap);
-
-        // Add additional stack slots for outgoing method parameters.
-        if (pointerSlots != null) {
-            for (StackSlot 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.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,129 @@
+/*
+ * 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.graal.lir;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+
+/**
+ * This class represents garbage collection and deoptimization information attached to a LIR instruction.
+ */
+public class LIRFrameState {
+    public final BytecodeFrame topFrame;
+    private final VirtualObject[] virtualObjects;
+    private final List<StackSlot> pointerSlots;
+    public final LabelRef exceptionEdge;
+    private DebugInfo debugInfo;
+
+    public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, List<StackSlot> pointerSlots, LabelRef exceptionEdge) {
+        this.topFrame = topFrame;
+        this.virtualObjects = virtualObjects;
+        this.pointerSlots = pointerSlots;
+        this.exceptionEdge = exceptionEdge;
+    }
+
+    public boolean hasDebugInfo() {
+        return debugInfo != null;
+    }
+
+    public DebugInfo 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 (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) {
+            processValues(cur.values, proc);
+        }
+        if (virtualObjects != null) {
+            for (VirtualObject obj : virtualObjects) {
+                processValues(obj.values(), proc);
+            }
+        }
+    }
+
+    /**
+     * We filter out constant and illegal values ourself before calling the procedure, so {@link OperandFlag#CONST} and {@link OperandFlag#ILLEGAL} need not be set.
+     */
+    private static final EnumSet<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK);
+
+    private void processValues(Value[] values, ValueProcedure proc) {
+        for (int i = 0; i < values.length; i++) {
+            Value value = values[i];
+            if (value instanceof MonitorValue) {
+                MonitorValue monitor = (MonitorValue) value;
+                if (processed(monitor.getOwner())) {
+                    monitor.setOwner(proc.doValue(monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS));
+                }
+
+            } else if (processed(value)) {
+                values[i] = proc.doValue(value, OperandMode.ALIVE, STATE_FLAGS);
+            }
+        }
+    }
+
+    private boolean processed(Value 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(BitSet registerRefMap, BitSet frameRefMap, FrameMap frameMap) {
+        debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap);
+
+        // Add additional stack slots for outgoing method parameters.
+        if (pointerSlots != null) {
+            for (StackSlot v : pointerSlots) {
+                frameMap.setReference(v, registerRefMap, frameRefMap);
+            }
+        }
+    }
+
+
+    @Override
+    public String toString() {
+        return debugInfo != null ? debugInfo.toString() : topFrame.toString();
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInsertionBuffer.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInsertionBuffer.java	Tue Jul 03 11:16:56 2012 +0200
@@ -31,7 +31,7 @@
  * <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()}, ...
+ * {@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.
  */
@@ -61,7 +61,7 @@
     }
 
     /**
-     * Initialize this buffer. This method must be called before using {@link #append()}.
+     * Initialize this buffer. This method must be called before using {@link #append}.
      */
     public void init(List<LIRInstruction> newLir) {
         assert !initialized() : "already initialized";
@@ -98,7 +98,7 @@
     }
 
     /**
-     * Append all enqueued instructions to the instruction list. After that, {@link init()} can be called again to re-use this buffer.
+     * Append all enqueued instructions to the instruction list. After that, {@link #init(List)} can be called again to re-use this buffer.
      */
     public void finish() {
         if (ops.size() > 0) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,8 +22,10 @@
  */
 package com.oracle.graal.lir;
 
-import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandMode.*;
 
+import java.lang.annotation.*;
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -69,6 +71,11 @@
     }
 
 
+    public abstract static class StateProcedure {
+        protected abstract void doState(LIRFrameState state);
+    }
+
+
     /**
      * Constants denoting how a LIR instruction uses an operand.
      */
@@ -79,28 +86,64 @@
          * to a Temp or Output operand. The value can be used again after the instruction, so the instruction must not
          * modify the register.
          */
-        Input,
+        USE,
 
         /**
          * 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,
+        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,
+        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,
+        DEF,
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public static @interface Use {
+        OperandFlag[] value() default REG;
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public static @interface Alive {
+        OperandFlag[] value() default REG;
     }
 
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public static @interface Temp {
+        OperandFlag[] value() default REG;
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public static @interface Def {
+        OperandFlag[] value() default REG;
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public static @interface State {
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.TYPE, ElementType.FIELD})
+    public static @interface Opcode {
+        String value() default "";
+    }
+
+
     /**
      * Flags for an operand.
      */
@@ -108,83 +151,61 @@
         /**
          * The value can be a {@link RegisterValue}.
          */
-        Register,
+        REG,
 
         /**
          * The value can be a {@link StackSlot}.
          */
-        Stack,
+        STACK,
 
         /**
          * The value can be a {@link Address}.
          */
-        Address,
+        ADDR,
 
         /**
          * The value can be a {@link Constant}.
          */
-        Constant,
+        CONST,
 
         /**
-         * The value can be {@link CiValue#IllegalValue}.
+         * The value can be {@link Value#IllegalValue}.
          */
-        Illegal,
+        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,
+        HINT,
 
         /**
          * 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,
+        UNINITIALIZED,
     }
 
+
     /**
      * For validity checking of the operand flags defined by instruction subclasses.
      */
-    private static final EnumMap<OperandMode, EnumSet<OperandFlag>> ALLOWED_FLAGS;
+    protected 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));
+        ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED));
+        ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED));
+        ALLOWED_FLAGS.put(TEMP,  EnumSet.of(REG, CONST, ILLEGAL, HINT));
+        ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, ILLEGAL, HINT));
     }
 
     /**
-     * The opcode of this instruction.
-     */
-    protected final Object code;
-
-    /**
-     * The output operands for this instruction (modified by the register allocator).
+     * The flags of the base and index value of an address.
      */
-    protected Value[] outputs;
-
-    /**
-     * The input operands for this instruction (modified by the register allocator).
-     */
-    protected Value[] inputs;
+    protected static final EnumSet<OperandFlag> ADDRESS_FLAGS = EnumSet.of(REG, ILLEGAL);
 
-    /**
-     * The alive operands for this instruction (modified by the register allocator).
-     */
-    protected Value[] alives;
-
-    /**
-     * The temp operands for this instruction (modified by the register allocator).
-     */
-    protected Value[] temps;
-
-    /**
-     * Used to emit debug information.
-     */
-    public final LIRDebugInfo info;
+    private final LIRInstructionClass instructionClass;
 
     /**
      * Instruction id for register allocation.
@@ -192,22 +213,11 @@
     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.
+     * Constructs a new LIR instruction.
      */
-    public LIRInstruction(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps) {
-        this.code = opcode;
-        this.outputs = outputs;
-        this.inputs = inputs;
-        this.alives = alives;
-        this.temps = temps;
-        this.info = info;
-        this.id = -1;
+    public LIRInstruction() {
+        instructionClass = LIRInstructionClass.get(getClass());
+        id = -1;
     }
 
     public abstract void emitCode(TargetMethodAssembler tasm);
@@ -222,100 +232,18 @@
     }
 
     /**
-     * Gets an input operand of this instruction.
-     *
-     * @param index the index of the operand requested.
-     * @return the {@code index}'th input operand.
-     */
-    protected final Value 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 Value 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 Value temp(int index) {
-        return temps[index];
-    }
-
-    /**
-     * Gets the result operand for this instruction.
-     *
-     * @return return the result operand
-     */
-    protected final Value output(int index) {
-        return outputs[index];
-    }
-
-    /**
      * Gets the instruction name.
      */
-    public String name() {
-        return code.toString();
+    public final String name() {
+        return instructionClass.getOpcode(this);
     }
 
-    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(Value[] values, OperandMode mode, ValueProcedure proc) {
-        for (int i = 0; i < values.length; i++) {
-            assert ALLOWED_FLAGS.get(mode).containsAll(flagsFor(mode, i));
-
-            Value value = values[i];
-            if (isAddress(value)) {
-                assert flagsFor(mode, i).contains(OperandFlag.Address);
-                Address address = asAddress(value);
-                address.setBase(proc.doValue(address.getBase(), mode, ADDRESS_FLAGS));
-                address.setIndex(proc.doValue(address.getIndex(), mode, ADDRESS_FLAGS));
-            } else {
-                values[i] = proc.doValue(values[i], mode, flagsFor(mode, i));
-            }
-        }
+    public final boolean hasOperands() {
+        return instructionClass.hasOperands() || hasState() || hasCall();
     }
 
-    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);
-                }
-            }
-        }
+    public final boolean hasState() {
+        return instructionClass.hasState(this);
     }
 
     /**
@@ -325,6 +253,31 @@
         return this instanceof StandardOp.CallOp;
     }
 
+
+    public final void forEachInput(ValueProcedure proc) {
+        instructionClass.forEachUse(this, proc);
+    }
+
+    public final void forEachAlive(ValueProcedure proc) {
+        instructionClass.forEachAlive(this, proc);
+    }
+
+    public final void forEachTemp(ValueProcedure proc) {
+        instructionClass.forEachTemp(this, proc);
+    }
+
+    public final void forEachOutput(ValueProcedure proc) {
+        instructionClass.forEachDef(this, proc);
+    }
+
+    public final void forEachState(ValueProcedure proc) {
+        instructionClass.forEachState(this, proc);
+    }
+
+    public final void forEachState(StateProcedure proc) {
+        instructionClass.forEachState(this, proc);
+    }
+
     /**
      * Iterates all register hints for the specified value, i.e., all preferred candidates for the register to be
      * assigned to the value.
@@ -339,32 +292,9 @@
      * @return The non-null value returned by the procedure, or null.
      */
     public Value forEachRegisterHint(Value value, OperandMode mode, ValueProcedure proc) {
-        Value[] 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++) {
-            Value result = proc.doValue(hints[i], null, null);
-            if (result != null) {
-                return result;
-            }
-        }
-        return null;
+        return instructionClass.forEachRegisterHint(this, mode, proc);
     }
 
-    /**
-     * 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 (cwimmer) 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() {
     }
@@ -377,72 +307,8 @@
         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 (Value 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 (Value input : inputs) {
-            buf.append(sep).append(input);
-            sep = ", ";
-        }
-        for (Value 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 (Value 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 (BytecodeFrame cur = info.topFrame; cur != null; cur = cur.caller()) {
-                buf.append(sep).append(cur.getBCI());
-                sep = ",";
-            }
-            buf.append("]");
-        }
-    }
-
     @Override
     public String toString() {
-        StringBuilder buf = new StringBuilder(name()).append(' ').append(operationString());
-        appendDebugInfo(buf);
-        return buf.toString();
+        return instructionClass.toString(this);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,608 @@
+/*
+ * 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.graal.lir;
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.StateProcedure;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+
+public class LIRInstructionClass {
+    // TODO(cwimmer) factor out the common methods of this class and NodeClass into a base class.
+
+    /**
+     * Interface used by {@link LIRInstructionClass#rescanAllFieldOffsets(CalcOffset)} to determine the offset (in bytes) of a field.
+     */
+    public interface CalcOffset {
+        long getOffset(Field field);
+    }
+
+    private static final Unsafe unsafe = getUnsafe();
+
+    private static Unsafe getUnsafe() {
+        try {
+            // this will only fail if graal is not part of the boot class path
+            return Unsafe.getUnsafe();
+        } catch (SecurityException e) {
+            // nothing to do
+        }
+        try {
+            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafeInstance.setAccessible(true);
+            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
+        } catch (Exception e) {
+            // currently we rely on being able to use Unsafe...
+            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
+        }
+    }
+
+    static class DefaultCalcOffset implements CalcOffset {
+        @Override
+        public long getOffset(Field field) {
+            return unsafe.objectFieldOffset(field);
+        }
+    }
+
+    private static final Class<?> INSTRUCTION_CLASS = LIRInstruction.class;
+    private static final Class<?> VALUE_CLASS = Value.class;
+    private static final Class<?> VALUE_ARRAY_CLASS = Value[].class;
+    private static final Class<?> STATE_CLASS = LIRFrameState.class;
+
+
+    private static final ConcurrentHashMap<Class< ? >, LIRInstructionClass> classes = new ConcurrentHashMap<>();
+
+    private final Class< ? > clazz;
+    private final int directUseCount;
+    private final long[] useOffsets;
+    private final EnumSet<OperandFlag>[] useFlags;
+    private final int directAliveCount;
+    private final long[] aliveOffsets;
+    private final EnumSet<OperandFlag>[] aliveFlags;
+    private final int directTempCount;
+    private final long[] tempOffsets;
+    private final EnumSet<OperandFlag>[] tempFlags;
+    private final int directDefCount;
+    private final long[] defOffsets;
+    private final EnumSet<OperandFlag>[] defFlags;
+
+    private final long[] stateOffsets;
+    private final long[] dataOffsets;
+
+    private final Map<Long, String> fieldNames;
+    private final Map<Long, Class<?>> fieldTypes;
+
+    private String opcodeConstant;
+    private long opcodeOffset;
+
+    @SuppressWarnings("unchecked")
+    public LIRInstructionClass(Class<?> clazz) {
+        assert INSTRUCTION_CLASS.isAssignableFrom(clazz);
+        this.clazz = clazz;
+
+        FieldScanner scanner = new FieldScanner(new DefaultCalcOffset());
+        scanner.scan(clazz);
+
+        OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class);
+        directUseCount = mode.scalarOffsets.size();
+        useOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets);
+        useFlags = arrayUsingSortedOffsets(mode.flags, useOffsets, new EnumSet[useOffsets.length]);
+
+        mode = scanner.valueAnnotations.get(LIRInstruction.Alive.class);
+        directAliveCount = mode.scalarOffsets.size();
+        aliveOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets);
+        aliveFlags = arrayUsingSortedOffsets(mode.flags, aliveOffsets, new EnumSet[aliveOffsets.length]);
+
+        mode = scanner.valueAnnotations.get(LIRInstruction.Temp.class);
+        directTempCount = mode.scalarOffsets.size();
+        tempOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets);
+        tempFlags = arrayUsingSortedOffsets(mode.flags, tempOffsets, new EnumSet[tempOffsets.length]);
+
+        mode = scanner.valueAnnotations.get(LIRInstruction.Def.class);
+        directDefCount = mode.scalarOffsets.size();
+        defOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets);
+        defFlags = arrayUsingSortedOffsets(mode.flags, defOffsets, new EnumSet[defOffsets.length]);
+
+        stateOffsets = sortedLongCopy(scanner.stateOffsets);
+        dataOffsets = sortedLongCopy(scanner.dataOffsets);
+
+        fieldNames = scanner.fieldNames;
+        fieldTypes = scanner.fieldTypes;
+
+        opcodeConstant = scanner.opcodeConstant;
+        opcodeOffset = scanner.opcodeOffset;
+    }
+
+    public static void rescanAllFieldOffsets(CalcOffset calc) {
+        for (LIRInstructionClass nodeClass : classes.values()) {
+            nodeClass.rescanFieldOffsets(calc);
+        }
+    }
+
+    private void rescanFieldOffsets(CalcOffset calc) {
+        FieldScanner scanner = new FieldScanner(calc);
+        scanner.scan(clazz);
+
+        OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class);
+        copyInto(useOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
+        mode = scanner.valueAnnotations.get(LIRInstruction.Alive.class);
+        copyInto(aliveOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
+        mode = scanner.valueAnnotations.get(LIRInstruction.Temp.class);
+        copyInto(tempOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
+        mode = scanner.valueAnnotations.get(LIRInstruction.Def.class);
+        copyInto(defOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
+
+        copyInto(stateOffsets, sortedLongCopy(scanner.stateOffsets));
+        copyInto(dataOffsets, sortedLongCopy(scanner.dataOffsets));
+
+        fieldNames.clear();
+        fieldNames.putAll(scanner.fieldNames);
+        fieldTypes.clear();
+        fieldTypes.putAll(scanner.fieldTypes);
+
+        opcodeConstant = scanner.opcodeConstant;
+        opcodeOffset = scanner.opcodeOffset;
+    }
+
+    private static void copyInto(long[] dest, long[] src) {
+        assert dest.length == src.length;
+        for (int i = 0; i < dest.length; i++) {
+            dest[i] = src[i];
+        }
+    }
+
+    public static final LIRInstructionClass get(Class<?> c) {
+        LIRInstructionClass clazz = classes.get(c);
+        if (clazz != null) {
+            return clazz;
+        }
+
+        // We can have a race of multiple threads creating the LIRInstructionClass at the same time.
+        // However, only one will be put into the map, and this is the one returned by all threads.
+        clazz = new LIRInstructionClass(c);
+        LIRInstructionClass oldClazz = classes.putIfAbsent(c, clazz);
+        if (oldClazz != null) {
+            return oldClazz;
+        } else {
+            return clazz;
+        }
+    }
+
+
+    private static class OperandModeAnnotation {
+        public final ArrayList<Long> scalarOffsets = new ArrayList<>();
+        public final ArrayList<Long> arrayOffsets = new ArrayList<>();
+        public final Map<Long, EnumSet<OperandFlag>> flags = new HashMap<>();
+    }
+
+    private static class FieldScanner {
+        public final CalcOffset calc;
+
+        public final Map<Class<? extends Annotation>, OperandModeAnnotation> valueAnnotations;
+        public final ArrayList<Long> stateOffsets = new ArrayList<>();
+        public final ArrayList<Long> dataOffsets = new ArrayList<>();
+
+        public final Map<Long, String> fieldNames = new HashMap<>();
+        public final Map<Long, Class<?>> fieldTypes = new HashMap<>();
+
+        private String opcodeConstant;
+        private long opcodeOffset;
+
+        public FieldScanner(CalcOffset calc) {
+            this.calc = calc;
+
+            valueAnnotations = new HashMap<>();
+            valueAnnotations.put(LIRInstruction.Use.class, new OperandModeAnnotation()); //LIRInstruction.Use.class));
+            valueAnnotations.put(LIRInstruction.Alive.class, new OperandModeAnnotation()); //LIRInstruction.Alive.class));
+            valueAnnotations.put(LIRInstruction.Temp.class, new OperandModeAnnotation()); //LIRInstruction.Temp.class));
+            valueAnnotations.put(LIRInstruction.Def.class, new OperandModeAnnotation()); //LIRInstruction.Def.class));
+        }
+
+        private OperandModeAnnotation getOperandModeAnnotation(Field field) {
+            OperandModeAnnotation result = null;
+            for (Entry<Class<? extends Annotation>, OperandModeAnnotation> entry  : valueAnnotations.entrySet()) {
+                Annotation annotation = field.getAnnotation(entry.getKey());
+                if (annotation != null) {
+                    assert result == null : "Field has two operand mode annotations: " + field;
+                    result = entry.getValue();
+                }
+            }
+            return result;
+        }
+
+        private static EnumSet<OperandFlag> getFlags(Field field) {
+            EnumSet<OperandFlag> result = EnumSet.noneOf(OperandFlag.class);
+            // Unfortunately, annotations cannot have class hierarchies or implement interfaces, so we have to duplicate the code for every operand mode.
+            // Unfortunately, annotations cannot have an EnumSet property, so we have to convert from arrays to EnumSet manually.
+            if (field.isAnnotationPresent(LIRInstruction.Use.class)) {
+                result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Use.class).value()));
+            } else if (field.isAnnotationPresent(LIRInstruction.Alive.class)) {
+                result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Alive.class).value()));
+            } else if (field.isAnnotationPresent(LIRInstruction.Temp.class)) {
+                result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Temp.class).value()));
+            } else if (field.isAnnotationPresent(LIRInstruction.Def.class)) {
+                result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Def.class).value()));
+            } else {
+                GraalInternalError.shouldNotReachHere();
+            }
+            return result;
+        }
+
+        public void scan(Class<?> clazz) {
+            if (clazz.getAnnotation(LIRInstruction.Opcode.class) != null) {
+                opcodeConstant = clazz.getAnnotation(LIRInstruction.Opcode.class).value();
+            }
+            opcodeOffset = -1;
+
+            Class<?> currentClazz = clazz;
+            do {
+                for (Field field : currentClazz.getDeclaredFields()) {
+                    if (Modifier.isStatic(field.getModifiers())) {
+                        continue;
+                    }
+
+                    Class< ? > type = field.getType();
+                    long offset = calc.getOffset(field);
+
+                    if (VALUE_CLASS.isAssignableFrom(type)) {
+                        assert Modifier.isProtected(field.getModifiers()) && !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final or private because it is modified by register allocator: " + field;
+                        OperandModeAnnotation annotation = getOperandModeAnnotation(field);
+                        assert annotation != null : "Field must have operand mode annotation: " + field;
+                        annotation.scalarOffsets.add(offset);
+                        annotation.flags.put(offset, getFlags(field));
+                    } else if (VALUE_ARRAY_CLASS.isAssignableFrom(type)) {
+                        OperandModeAnnotation annotation = getOperandModeAnnotation(field);
+                        assert annotation != null : "Field must have operand mode annotation: " + field;
+                        annotation.arrayOffsets.add(offset);
+                        annotation.flags.put(offset, getFlags(field));
+                    } else if (STATE_CLASS.isAssignableFrom(type)) {
+                        assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field;
+                        assert field.getAnnotation(LIRInstruction.State.class) != null : "Field must have state annotation: " + field;
+                        stateOffsets.add(offset);
+                    } else {
+                        assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field;
+                        assert field.getAnnotation(LIRInstruction.State.class) == null : "Field must not have state annotation: " + field;
+                        dataOffsets.add(offset);
+                    }
+                    fieldNames.put(offset, field.getName());
+                    fieldTypes.put(offset, type);
+
+                    if (field.getAnnotation(LIRInstruction.Opcode.class) != null) {
+                        assert opcodeConstant == null && opcodeOffset == -1 : "Can have only one Opcode definition: " + clazz;
+                        opcodeOffset = offset;
+                    }
+                }
+                currentClazz = currentClazz.getSuperclass();
+            } while (currentClazz != LIRInstruction.class);
+
+            if (opcodeConstant == null && opcodeOffset == -1) {
+                opcodeConstant = clazz.getSimpleName();
+                if (opcodeConstant.endsWith("Op")) {
+                    opcodeConstant = opcodeConstant.substring(0, opcodeConstant.length() - 2);
+                }
+            }
+        }
+    }
+
+    private static <T> T[] arrayUsingSortedOffsets(Map<Long, T> map, long[] sortedOffsets, T[] result) {
+        for (int i = 0; i < sortedOffsets.length; i++) {
+            result[i] = map.get(sortedOffsets[i]);
+        }
+        return result;
+    }
+
+    private static long[] sortedLongCopy(ArrayList<Long> list1) {
+        Collections.sort(list1);
+        long[] result = new long[list1.size()];
+        for (int i = 0; i < list1.size(); i++) {
+            result[i] = list1.get(i);
+        }
+        return result;
+    }
+
+    private static long[] sortedLongCopy(ArrayList<Long> list1, ArrayList<Long> list2) {
+        Collections.sort(list1);
+        Collections.sort(list2);
+        long[] result = new long[list1.size() + list2.size()];
+        for (int i = 0; i < list1.size(); i++) {
+            result[i] = list1.get(i);
+        }
+        for (int i = 0; i < list2.size(); i++) {
+            result[list1.size() + i] = list2.get(i);
+        }
+        return result;
+    }
+
+
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" use[");
+        for (int i = 0; i < useOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(useOffsets[i]);
+        }
+        str.append("] alive[");
+        for (int i = 0; i < aliveOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(aliveOffsets[i]);
+        }
+        str.append("] temp[");
+        for (int i = 0; i < tempOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(tempOffsets[i]);
+        }
+        str.append("] def[");
+        for (int i = 0; i < defOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(defOffsets[i]);
+        }
+        str.append("] state[");
+        for (int i = 0; i < stateOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(stateOffsets[i]);
+        }
+        str.append("] data[");
+        for (int i = 0; i < dataOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(dataOffsets[i]);
+        }
+        str.append("]");
+        return str.toString();
+    }
+
+
+    public final String getOpcode(LIRInstruction obj) {
+        if (opcodeConstant != null) {
+            return opcodeConstant;
+        }
+        assert opcodeOffset != -1;
+        return unsafe.getObject(obj, opcodeOffset).toString();
+    }
+
+    public final boolean hasOperands() {
+        return useOffsets.length > 0 || aliveOffsets.length > 0 || tempOffsets.length > 0 || defOffsets.length > 0;
+    }
+
+    public final boolean hasState(LIRInstruction obj) {
+        for (int i = 0; i < stateOffsets.length; i++) {
+            if (getState(obj, stateOffsets[i]) != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public final void forEachUse(LIRInstruction obj, ValueProcedure proc) {
+        forEach(obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc);
+    }
+
+    public final void forEachAlive(LIRInstruction obj, ValueProcedure proc) {
+        forEach(obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc);
+    }
+
+    public final void forEachTemp(LIRInstruction obj, ValueProcedure proc) {
+        forEach(obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc);
+    }
+
+    public final void forEachDef(LIRInstruction obj, ValueProcedure proc) {
+        forEach(obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc);
+    }
+
+    public final void forEachState(LIRInstruction obj, ValueProcedure proc) {
+        for (int i = 0; i < stateOffsets.length; i++) {
+            LIRFrameState state = getState(obj, stateOffsets[i]);
+            if (state != null) {
+                state.forEachState(proc);
+            }
+        }
+    }
+
+    public final void forEachState(LIRInstruction obj, StateProcedure proc) {
+        for (int i = 0; i < stateOffsets.length; i++) {
+            LIRFrameState state = getState(obj, stateOffsets[i]);
+            if (state != null) {
+                proc.doState(state);
+            }
+        }
+    }
+
+    private static void forEach(LIRInstruction obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, ValueProcedure proc) {
+        for (int i = 0; i < offsets.length; i++) {
+            assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]);
+
+            if (i < directCount) {
+                Value value = getValue(obj, offsets[i]);
+                if (isAddress(value)) {
+                    doAddress(asAddress(value), mode, flags[i], proc);
+                } else {
+                    setValue(obj, offsets[i], proc.doValue(value, mode, flags[i]));
+                }
+            } else {
+                Value[] values = getValueArray(obj, offsets[i]);
+                for (int j = 0; j < values.length; j++) {
+                    Value value = values[j];
+                    if (isAddress(value)) {
+                        doAddress(asAddress(value), mode, flags[i], proc);
+                    } else {
+                        values[j] = proc.doValue(value, mode, flags[i]);
+                    }
+                }
+            }
+        }
+    }
+
+    private static void doAddress(Address address, OperandMode mode, EnumSet<OperandFlag> flags, ValueProcedure proc) {
+        assert flags.contains(OperandFlag.ADDR);
+        address.setBase(proc.doValue(address.getBase(), mode, LIRInstruction.ADDRESS_FLAGS));
+        address.setIndex(proc.doValue(address.getIndex(), mode, LIRInstruction.ADDRESS_FLAGS));
+    }
+
+    public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, ValueProcedure proc) {
+        int hintDirectCount = 0;
+        long[] hintOffsets = null;
+        if (mode == OperandMode.USE) {
+            hintDirectCount = directDefCount;
+            hintOffsets = defOffsets;
+        } else if (mode == OperandMode.DEF) {
+            hintDirectCount = directUseCount;
+            hintOffsets = useOffsets;
+        } else {
+            return null;
+        }
+
+        for (int i = 0; i < hintOffsets.length; i++) {
+            if (i < hintDirectCount) {
+                Value hintValue = getValue(obj, hintOffsets[i]);
+                Value result = proc.doValue(hintValue, null, null);
+                if (result != null) {
+                    return result;
+                }
+            } else {
+                Value[] hintValues = getValueArray(obj, hintOffsets[i]);
+                for (int j = 0; j < hintValues.length; j++) {
+                    Value hintValue = hintValues[j];
+                    Value result = proc.doValue(hintValue, null, null);
+                    if (result != null) {
+                        return result;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private static Value getValue(LIRInstruction obj, long offset) {
+        return (Value) unsafe.getObject(obj, offset);
+    }
+
+    private static void setValue(LIRInstruction obj, long offset, Value value) {
+        unsafe.putObject(obj, offset, value);
+    }
+
+    private static Value[] getValueArray(LIRInstruction obj, long offset) {
+        return (Value[]) unsafe.getObject(obj, offset);
+    }
+
+    private static LIRFrameState getState(LIRInstruction obj, long offset) {
+        return (LIRFrameState) unsafe.getObject(obj, offset);
+    }
+
+
+    public String toString(LIRInstruction obj) {
+        StringBuilder result = new StringBuilder();
+
+        appendValues(result, obj, "", " = ", "(", ")", new String[] {""}, defOffsets);
+        result.append(getOpcode(obj).toUpperCase());
+        appendValues(result, obj, " ", "", "(", ")", new String[] {"", "~"}, useOffsets, aliveOffsets);
+        appendValues(result, obj, " ", "", "{", "}", new String[] {""}, tempOffsets);
+
+        for (int i = 0; i < dataOffsets.length; i++) {
+            if (dataOffsets[i] == opcodeOffset) {
+                continue;
+            }
+            result.append(" ").append(fieldNames.get(dataOffsets[i])).append(": ").append(getFieldString(obj, dataOffsets[i]));
+        }
+
+        for (int i = 0; i < stateOffsets.length; i++) {
+            LIRFrameState state = getState(obj, stateOffsets[i]);
+            if (state != null) {
+                result.append(" ").append(fieldNames.get(stateOffsets[i])).append(" [bci:");
+                String sep = "";
+                for (BytecodeFrame cur = state.topFrame; cur != null; cur = cur.caller()) {
+                    result.append(sep).append(cur.getBCI());
+                    sep = ", ";
+                }
+                result.append("]");
+            }
+        }
+
+        return result.toString();
+    }
+
+    private void appendValues(StringBuilder result, LIRInstruction obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]...moffsets) {
+        int total = 0;
+        for (long[] offsets : moffsets) {
+            total += offsets.length;
+        }
+        if (total == 0) {
+            return;
+        }
+
+        result.append(start);
+        if (total > 1) {
+            result.append(startMultiple);
+        }
+        String sep = "";
+        for (int i = 0; i < moffsets.length; i++) {
+            long[] offsets = moffsets[i];
+
+            for (int j = 0; j < offsets.length; j++) {
+                result.append(sep).append(prefix[i]);
+                long offset = offsets[j];
+                if (total > 1) {
+                    result.append(fieldNames.get(offset)).append(": ");
+                }
+                result.append(getFieldString(obj, offset));
+                sep = ", ";
+            }
+        }
+        if (total > 1) {
+            result.append(endMultiple);
+        }
+        result.append(end);
+    }
+
+    private String getFieldString(Object obj, long offset) {
+        Class<?> type = fieldTypes.get(offset);
+        if (type == int.class) {
+            return String.valueOf(unsafe.getInt(obj, offset));
+        } else if (type == long.class) {
+            return String.valueOf(unsafe.getLong(obj, offset));
+        } else if (type == boolean.class) {
+            return String.valueOf(unsafe.getBoolean(obj, offset));
+        } else if (type == float.class) {
+            return String.valueOf(unsafe.getFloat(obj, offset));
+        } else if (type == double.class) {
+            return String.valueOf(unsafe.getDouble(obj, offset));
+        } else if (!type.isPrimitive()) {
+            Object value = unsafe.getObject(obj, offset);
+            if (!type.isArray()) {
+                return String.valueOf(value);
+            } else if (type == int[].class) {
+                return Arrays.toString((int[]) value);
+            } else if (type == double[].class) {
+                return Arrays.toString((double[]) value);
+            } else if (!type.getComponentType().isPrimitive()) {
+                return Arrays.toString((Object[]) value);
+            }
+        }
+        assert false : "unhandled field type: " + type;
+        return "";
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Tue Jul 03 11:16:56 2012 +0200
@@ -171,7 +171,7 @@
 
         } else if (isAllocatableRegister(value)) {
             int regNum = asRegister(value).number;
-            if (mode == OperandMode.Alive) {
+            if (mode == OperandMode.ALIVE) {
                 curRegistersDefined.set(regNum);
             }
 
@@ -202,7 +202,7 @@
             assert curInstruction != null;
             variableDefinitions[variableIdx] = curInstruction;
             assert !curVariablesLive.get(variableIdx);
-            if (mode == OperandMode.Output) {
+            if (mode == OperandMode.DEF) {
                 curVariablesLive.set(variableIdx);
             }
 
@@ -216,7 +216,7 @@
             curRegistersDefined.set(regNum);
 
             if (beforeRegisterAllocation) {
-                if (mode == OperandMode.Output) {
+                if (mode == OperandMode.DEF) {
                     curRegistersLive[regNum] = value;
                 } else {
                     curRegistersLive[regNum] = null;
@@ -227,11 +227,11 @@
     }
 
     private static Value allowed(Object op, Value 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))) {
+        if ((isVariable(value)  && flags.contains(OperandFlag.REG)) ||
+            (isRegister(value)  && flags.contains(OperandFlag.REG)) ||
+            (isStackSlot(value) && flags.contains(OperandFlag.STACK)) ||
+            (isConstant(value)  && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) ||
+            (isIllegal(value)   && flags.contains(OperandFlag.ILLEGAL))) {
             return value;
         }
         TTY.println("instruction %s", op);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRXirInstruction.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRXirInstruction.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,39 +23,47 @@
 package com.oracle.graal.lir;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-
-import java.util.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.max.cri.xir.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 
 public abstract class LIRXirInstruction extends LIRInstruction {
+    @Opcode protected final String opcode;
+    @Def({REG, ILLEGAL}) protected Value outputOperand;
+    @Alive({REG, CONST, ILLEGAL}) protected Value[] inputs;
+    @Temp({REG, CONST, ILLEGAL}) protected Value[] temps;
+    @State protected LIRFrameState state;
+    @State protected LIRFrameState stateAfter;
 
-    public final Value[] originalOperands;
+    // Defined as Object[] so that the magic processing of Value[] does not complain this field is not annotated.
+    public final Object[] 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,
+    public LIRXirInstruction(XirSnippet snippet,
                              Value[] originalOperands,
                              Value outputOperand,
                              Value[] inputs, Value[] temps,
                              int[] inputOperandIndices, int[] tempOperandIndices,
                              int outputOperandIndex,
-                             LIRDebugInfo info,
-                             LIRDebugInfo infoAfter,
+                             LIRFrameState state,
+                             LIRFrameState stateAfter,
                              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 Value[] {outputOperand} : LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, inputs, temps);
-        this.infoAfter = infoAfter;
+        this.opcode = "XIR: " + snippet.template;
+        this.outputOperand = outputOperand;
+        this.inputs = inputs;
+        this.temps = temps;
+        this.state = state;
+        this.stateAfter = stateAfter;
         this.snippet = snippet;
         this.inputOperandIndices = inputOperandIndices;
         this.tempOperandIndices = tempOperandIndices;
@@ -66,31 +74,16 @@
         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 Value[] getOperands() {
         for (int i = 0; i < inputOperandIndices.length; i++) {
-            originalOperands[inputOperandIndices[i]] = alive(i);
+            originalOperands[inputOperandIndices[i]] = inputs[i];
         }
         for (int i = 0; i < tempOperandIndices.length; i++) {
-            originalOperands[tempOperandIndices[i]] = temp(i);
+            originalOperands[tempOperandIndices[i]] = temps[i];
         }
         if (outputOperandIndex != -1) {
-            originalOperands[outputOperandIndex] = output(0);
+            originalOperands[outputOperandIndex] = outputOperand;
         }
-        return originalOperands;
-    }
-
-    @Override
-    public String name() {
-        return "XIR: " + snippet.template;
+        return (Value[]) originalOperands;
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Tue Jul 03 11:16:56 2012 +0200
@@ -62,7 +62,8 @@
     /**
      * 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}.
+     * is modified between the creation of the reference and the call to {@link #forLabel(Label)}.
+     *
      * @param block The base block that contains the successor list.
      * @param suxIndex The index of the successor.
      * @return The newly created label reference.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,12 +22,10 @@
  */
 package com.oracle.graal.lir;
 
-import java.util.*;
-
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.asm.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 /**
  * A collection of machine-independent LIR operations, as well as interfaces to be implemented for specific kinds or LIR
@@ -38,6 +36,15 @@
     private static Value[] EMPTY = new Value[0];
 
     /**
+     * Marker interface for LIR ops that can fall through to the next operation, like a switch statement.
+     * setFallThroughTarget(null) can be used to make the operation fall through to the next one.
+     */
+    public interface FallThroughOp {
+        LabelRef fallThroughTarget();
+        void setFallThroughTarget(LabelRef target);
+    }
+
+    /**
      * LIR operation that defines the position of a label.
      * The first operation of every block must implement this interface.
      */
@@ -45,16 +52,11 @@
         private final Label label;
         private final boolean align;
 
-        protected LabelOp(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps, Label label, boolean align) {
-            super(opcode, outputs, info, inputs, alives, temps);
+        public LabelOp(Label label, boolean align) {
             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) {
@@ -63,40 +65,25 @@
             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, Value[] phiDefinitions) {
-            super("PHI_LABEL", phiDefinitions, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, label, align);
-        }
+        @Def({REG, STACK}) protected Value[] phiDefinitions;
 
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Output) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+        public PhiLabelOp(Label label, boolean align, Value[] phiDefinitions) {
+            super(label, align);
+            this.phiDefinitions = phiDefinitions;
         }
 
         public void markResolved() {
-            outputs = EMPTY;
+            phiDefinitions = EMPTY;
         }
 
         public Value[] getPhiDefinitions() {
-            return outputs;
+            return phiDefinitions;
         }
     }
 
@@ -109,14 +96,11 @@
      */
     public static class JumpOp extends LIRInstruction {
         private final LabelRef destination;
+        @State protected LIRFrameState state;
 
-        protected JumpOp(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps, LabelRef destination) {
-            super(opcode, outputs, info, inputs, alives, temps);
+        public JumpOp(LabelRef destination, LIRFrameState state) {
             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);
+            this.state = state;
         }
 
         @Override
@@ -124,40 +108,25 @@
             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, Value[] phiInputs) {
-            super("PHI_JUMP", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, phiInputs, LIRInstruction.NO_OPERANDS, destination);
-        }
+        @Alive({REG, STACK, CONST}) protected Value[] phiInputs;
 
-        @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 PhiJumpOp(LabelRef destination, Value[] phiInputs) {
+            super(destination, null);
+            this.phiInputs = phiInputs;
         }
 
         public void markResolved() {
-            alives = EMPTY;
+            phiInputs = EMPTY;
         }
 
         public Value[] getPhiInputs() {
-            return alives;
+            return phiInputs;
         }
     }
 
@@ -191,21 +160,15 @@
      * In particular, it is not the actual method prologue.
      */
     public static final class ParametersOp extends LIRInstruction {
+        @Def({REG, STACK}) protected Value[] params;
+
         public ParametersOp(Value[] params) {
-            super("PARAMS", params, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.params = params;
         }
 
         @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();
-        }
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Tue Jul 03 11:16:56 2012 +0200
@@ -159,7 +159,7 @@
         return targetMethod;
     }
 
-    public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) {
+    public void recordExceptionHandlers(int pcOffset, LIRFrameState info) {
         if (info != null) {
             if (info.exceptionEdge != null) {
                 if (exceptionInfoList == null) {
@@ -170,7 +170,7 @@
         }
     }
 
-    public void recordImplicitException(int pcOffset, LIRDebugInfo info) {
+    public void recordImplicitException(int pcOffset, LIRFrameState info) {
         // record an implicit exception point
         if (info != null) {
             assert lastSafepointPos < pcOffset : lastSafepointPos + "<" + pcOffset;
@@ -180,21 +180,21 @@
         }
     }
 
-    public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRDebugInfo info) {
+    public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRFrameState info) {
         DebugInfo 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) {
+    public void recordIndirectCall(int posBefore, int posAfter, Object callTarget, LIRFrameState info) {
         DebugInfo 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) {
+    public void recordSafepoint(int pos, LIRFrameState info) {
         // safepoints always need debug info
         DebugInfo debugInfo = info.debugInfo();
         assert lastSafepointPos < pos;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.nodes</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +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.graal.cri;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-
-public interface CiLoweringTool {
-    ExtendedRiRuntime getRuntime();
-    ValueNode getGuardAnchor();
-    ValueNode createNullCheckGuard(ValueNode object, long leafGraphId);
-    ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, long leafGraphId);
-    ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated, long leafGraphId);
-    Assumptions assumptions();
-}
-
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/ExtendedRiRuntime.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +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.graal.cri;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-
-/**
- * Graal-specific extensions for the runtime interface that must be implemented by the VM.
- */
-public interface ExtendedRiRuntime extends CodeCacheProvider {
-
-    void lower(Node n, CiLoweringTool tool);
-
-    StructuredGraph intrinsicGraph(ResolvedJavaMethod caller, int bci, ResolvedJavaMethod method, List<? extends Node> parameters);
-
-    CompilationResult compile(ResolvedJavaMethod method, StructuredGraph graph);
-
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/RiGraphCache.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * 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.cri;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-
-
-public interface RiGraphCache {
-
-    void put(StructuredGraph graph);
-
-    StructuredGraph get(ResolvedJavaMethod method);
-
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -31,8 +31,8 @@
  * The {@code ControlSplitNode} is a base class for all instructions that split the control flow (ie. have more than one successor).
  */
 public abstract class ControlSplitNode extends FixedNode {
-
     @Successor private final NodeSuccessorList<BeginNode> blockSuccessors;
+    protected double[] branchProbability;
 
     public BeginNode blockSuccessor(int index) {
         return blockSuccessors.get(index);
@@ -46,8 +46,6 @@
         return blockSuccessors.size();
     }
 
-    protected final double[] branchProbability;
-
     public ControlSplitNode(Stamp stamp, BeginNode[] blockSuccessors, double[] branchProbability) {
         super(stamp);
         assert branchProbability.length == blockSuccessors.length;
@@ -63,14 +61,6 @@
         branchProbability[successorIndex] = x;
     }
 
-    /**
-     * Gets the successor corresponding to the default (fall through) case.
-     * @return the default successor
-     */
-    public FixedNode defaultSuccessor() {
-        return blockSuccessor(blockSuccessorCount() - 1);
-    }
-
     public Iterable<BeginNode> blockSuccessors() {
         return new Iterable<BeginNode>() {
             @Override
@@ -113,4 +103,11 @@
         }
         return idx;
     }
+
+    @Override
+    public ControlSplitNode clone(Graph into) {
+        ControlSplitNode csn = (ControlSplitNode) super.clone(into);
+        csn.branchProbability = Arrays.copyOf(branchProbability, branchProbability.length);
+        return csn;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -92,7 +91,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(tool.createGuard(condition, deoptReason, action, negated, leafGraphId)));
         ((StructuredGraph) graph()).replaceFixedWithFixed(this, newAnchor);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Tue Jul 03 11:16:56 2012 +0200
@@ -113,7 +113,6 @@
      *
      * @param method the method for this frame state
      * @param bci the bytecode index of the frame state
-     * @param localsSize number of locals
      * @param stackSize size of the stack
      * @param rethrowException if true the VM should re-throw the exception on top of the stack when deopt'ing using this framestate
      */
@@ -326,7 +325,7 @@
         String nl = CodeUtil.NEW_LINE;
         FrameState fs = frameState;
         while (fs != null) {
-            CodeUtil.appendLocation(sb, fs.method, fs.bci).append(nl);
+            MetaUtil.appendLocation(sb, fs.method, fs.bci).append(nl);
             sb.append("locals: [");
             for (int i = 0; i < fs.localsSize(); i++) {
                 sb.append(i == 0 ? "" : ", ").append(fs.localAt(i) == null ? "_" : fs.localAt(i).toString(Verbosity.Id));
@@ -357,7 +356,7 @@
         Map<Object, Object> properties = super.getDebugProperties();
         properties.put("bci", bci);
         if (method != null) {
-            properties.put("method", CodeUtil.format("%H.%n(%p):%r", method));
+            properties.put("method", MetaUtil.format("%H.%n(%p):%r", method));
             StackTraceElement ste = method.toStackTraceElement(bci);
             if (ste.getFileName() != null && ste.getLineNumber() >= 0) {
                 properties.put("source", ste.getFileName() + ":" + ste.getLineNumber());
@@ -401,4 +400,31 @@
             outerFrameState().applyToNonVirtual(closure);
         }
     }
+
+    @Override
+    public void applyToVirtual(VirtualClosure closure) {
+        closure.apply(this);
+        for (VirtualObjectState state : virtualObjectMappings) {
+            state.applyToVirtual(closure);
+        }
+        if (outerFrameState() != null) {
+            outerFrameState().applyToVirtual(closure);
+        }
+    }
+
+    @Override
+    public boolean isPartOfThisState(VirtualState state) {
+        if (state == this) {
+            return true;
+        }
+        if (outerFrameState() != null && outerFrameState().isPartOfThisState(state)) {
+            return true;
+        }
+        for (VirtualObjectState objectState : virtualObjectMappings) {
+            if (objectState.isPartOfThisState(state)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -35,7 +35,7 @@
  * state, they can move around freely and will always use the correct frame state when the nodes are scheduled (i.e.,
  * the last emitted frame state). The node that is guarded has a data dependency on the guard and the guard in turn has
  * a data dependency on the condition. A guard may only be executed if it is guaranteed that the guarded node is
- * executed too (if no exceptions are thrown). Therefore, an {@linkplain AnchorNode anchor} is placed after a control
+ * executed too (if no exceptions are thrown). Therefore, an anchor is placed after a control
  * flow split and the guard has a data dependency to the anchor. The anchor is the most distant node that is
  * post-dominated by the guarded node and the guard can be scheduled anywhere between those two nodes. This ensures
  * maximum flexibility for the guard node and guarantees that deoptimization occurs only if the control flow would have
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -36,6 +36,7 @@
 public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, SplitTypeFeedbackProvider, Negatable {
     public static final int TRUE_EDGE = 0;
     public static final int FALSE_EDGE = 1;
+    private final long leafGraphId;
 
     @Input private BooleanNode compare;
 
@@ -48,9 +49,14 @@
         compare = x;
     }
 
-    public IfNode(BooleanNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double takenProbability) {
+    public IfNode(BooleanNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double takenProbability, long leafGraphId) {
         super(StampFactory.forVoid(), new BeginNode[] {BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor)}, new double[] {takenProbability, 1 - takenProbability});
         this.compare = condition;
+        this.leafGraphId = leafGraphId;
+    }
+
+    public long leafGraphId() {
+        return leafGraphId;
     }
 
     /**
@@ -125,6 +131,7 @@
                     if (!phis.hasNext()) {
                         // empty if construct with no phis: remove it
                         removeEmptyIf(tool);
+                        return;
                     } else {
                         PhiNode singlePhi = phis.next();
                         if (!phis.hasNext()) {
@@ -142,6 +149,7 @@
                                 MaterializeNode materialize = MaterializeNode.create(compare(), graph(), trueValue, falseValue);
                                 ((StructuredGraph) graph()).replaceFloating(singlePhi, materialize);
                                 removeEmptyIf(tool);
+                                return;
                             }
                         }
                     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
@@ -47,9 +46,7 @@
      * Constructs a new Invoke instruction.
      *
      * @param bci the bytecode index of the original invoke (used for debug infos)
-     * @param opcode the opcode of the invoke
-     * @param target the target method being called
-     * @param args the list of instructions producing arguments to the invocation, including the receiver object
+     * @param callTarget the target method being called
      */
     public InvokeNode(MethodCallTargetNode callTarget, int bci, long leafGraphId) {
         super(callTarget.returnStamp());
@@ -92,7 +89,7 @@
     public Map<Object, Object> getDebugProperties() {
         Map<Object, Object> debugProperties = super.getDebugProperties();
         if (callTarget != null && callTarget.targetMethod() != null) {
-            debugProperties.put("targetMethod", CodeUtil.format("%h.%n(%p)", callTarget.targetMethod()));
+            debugProperties.put("targetMethod", MetaUtil.format("%h.%n(%p)", callTarget.targetMethod()));
         }
         return debugProperties;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
@@ -44,11 +43,6 @@
     private boolean useForInlining;
     private final long leafGraphId;
 
-    /**
-     * @param kind
-     * @param blockSuccessors
-     * @param branchProbability
-     */
     public InvokeWithExceptionNode(MethodCallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci, long leafGraphId) {
         super(callTarget.returnStamp(), new BeginNode[]{null, exceptionEdge}, new double[]{1.0, 0.0});
         this.bci = bci;
@@ -162,7 +156,7 @@
         Map<Object, Object> debugProperties = super.getDebugProperties();
         debugProperties.put("memoryCheckpoint", "true");
         if (callTarget != null && callTarget.targetMethod() != null) {
-            debugProperties.put("targetMethod", CodeUtil.format("%h.%n(%p)", callTarget.targetMethod()));
+            debugProperties.put("targetMethod", MetaUtil.format("%h.%n(%p)", callTarget.targetMethod()));
         }
         return debugProperties;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -61,7 +61,7 @@
     }
 
     /**
-     * Create a non-value phi ({@link PhiType#Memory} or {@link PhiType#Virtual}) with the specified kind.
+     * Create a non-value phi ({@link PhiType#Memory} with the specified kind.
      * @param type the type of the new phi
      * @param merge the merge that the new phi belongs to
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Jul 03 11:16:56 2012 +0200
@@ -253,7 +253,7 @@
         for (int i = 0; i < node.blockSuccessorCount(); i++) {
             BeginNode successor = node.blockSuccessor(i);
             node.setBlockSuccessor(i, null);
-            if (successor != begin && successor.isAlive()) {
+            if (successor != null && successor != begin && successor.isAlive()) {
                 GraphUtil.killCFG(successor);
             }
         }
@@ -261,7 +261,7 @@
             node.replaceAtPredecessor(begin);
             node.safeDelete();
         } else {
-            assert node.isDeleted();
+            assert node.isDeleted() : node + " " + begin;
         }
     }
 
@@ -350,8 +350,8 @@
         // evacuateGuards
         merge.prepareDelete((FixedNode) singleEnd.predecessor());
         merge.safeDelete();
-        if (stateAfter != null && stateAfter.usages().isEmpty()) {
-            stateAfter.safeDelete();
+        if (stateAfter != null && stateAfter.isAlive() && stateAfter.usages().isEmpty()) {
+            GraphUtil.killWithUnusedFloatingInputs(stateAfter);
         }
         if (sux == null) {
             singleEnd.replaceAtPredecessor(null);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -150,6 +150,7 @@
     }
 
     public <T extends Stamp> boolean verifyStamp(Class<T> stampClass) {
+        assert stamp != null;
         assert stampClass.isInstance(stamp) : this + " (" + GraphUtil.approxSourceLocation(this) + ") has unexpected stamp type: expected " + stampClass.getName() +
             ", got " + stamp.getClass().getName();
         return true;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java	Tue Jul 03 11:16:56 2012 +0200
@@ -97,7 +97,7 @@
     /**
      * Converts a given instruction to a value string. The representation of an node as
      * a value is formed by concatenating the {@linkplain com.oracle.graal.api.meta.Kind#typeChar character} denoting its
-     * {@linkplain ValueNode#kind kind} and its {@linkplain Node#id()}. For example, {@code "i13"}.
+     * {@linkplain ValueNode#kind kind} and its id. For example, {@code "i13"}.
      *
      * @param value the instruction to convert to a value string. If {@code value == null}, then "-" is returned.
      * @return the instruction representation as a string
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java	Tue Jul 03 11:16:56 2012 +0200
@@ -34,8 +34,16 @@
         void apply(Node usage, T node);
     }
 
+    public interface VirtualClosure {
+        void apply(VirtualState node);
+    }
+
     public abstract VirtualState duplicateWithVirtualState();
 
     public abstract void applyToNonVirtual(NodeClosure<? super ValueNode> closure);
 
+    public abstract void applyToVirtual(VirtualClosure closure);
+
+    public abstract boolean isPartOfThisState(VirtualState state);
+
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java	Tue Jul 03 11:16:56 2012 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.max.cri.util.*;
+import com.oracle.max.criutils.*;
 
 /**
  * Condition codes used in conditionals.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -74,10 +74,8 @@
 
     /**
      * Constructs a new Convert instance.
-     * @param kind the result type of this instruction
      * @param opcode the operation
      * @param value the instruction producing the input value
-     * @param graph
      */
     public ConvertNode(Op opcode, ValueNode value) {
         super(StampFactory.forKind(opcode.to.stackKind()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -46,7 +45,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) graph();
 
         BooleanNode equalComp;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,168 @@
+/*
+ * 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.graal.nodes.extended;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+
+/**
+ * The {@code IntegerSwitchNode} represents a switch on integer keys, with a sorted array of key values.
+ * The actual implementation of the switch will be decided by the backend.
+ */
+public final class IntegerSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable {
+
+    private final int[] keys;
+
+    /**
+     * Constructs a integer switch instruction. The keyProbabilities and keySuccessors array contain key.length + 1
+     * entries, the last entry describes the default (fall through) case.
+     *
+     * @param value the instruction producing the value being switched on
+     * @param successors the list of successors
+     * @param keys the sorted list of keys
+     * @param keyProbabilities the probabilities of the keys
+     * @param keySuccessors the successor index for each key
+     */
+    public IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+        super(value, successors, successorProbabilites(successors.length, keySuccessors, keyProbabilities), keySuccessors, keyProbabilities);
+        assert keySuccessors.length == keys.length + 1;
+        assert keySuccessors.length == keyProbabilities.length;
+        this.keys = keys;
+    }
+
+    /**
+     * Constructs a integer switch instruction. The keyProbabilities and keySuccessors array contain key.length + 1
+     * entries, the last entry describes the default (fall through) case.
+     *
+     * @param value the instruction producing the value being switched on
+     * @param successorCount the number of successors
+     * @param keys the sorted list of keys
+     * @param keyProbabilities the probabilities of the keys
+     * @param keySuccessors the successor index for each key
+     */
+    public IntegerSwitchNode(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+        this(value, new BeginNode[successorCount], keys, keyProbabilities, keySuccessors);
+    }
+
+    /**
+     * Gets the key at the specified index.
+     * @param i the index
+     * @return the key at that index
+     */
+    @Override
+    public Constant keyAt(int i) {
+        return Constant.forInt(keys[i]);
+    }
+
+    @Override
+    public int keyCount() {
+        return keys.length;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        gen.emitSwitch(this);
+    }
+
+    @Override
+    public void simplify(SimplifierTool tool) {
+        if (value() instanceof ConstantNode) {
+            int constant = value().asConstant().asInt();
+
+            int survivingEdge = keySuccessorIndex(keyCount());
+            for (int i = 0; i < keyCount(); i++) {
+                if (keys[i] == constant) {
+                    survivingEdge = keySuccessorIndex(i);
+                }
+            }
+            for (int i = 0; i < blockSuccessorCount(); i++) {
+                if (i != survivingEdge) {
+                    tool.deleteBranch(blockSuccessor(i));
+                }
+            }
+            tool.addToWorkList(blockSuccessor(survivingEdge));
+            ((StructuredGraph) graph()).removeSplitPropagate(this, survivingEdge);
+        }
+        if (value() != null) {
+            IntegerStamp stamp = value().integerStamp();
+            if (!stamp.isUnrestricted()) {
+                int validKeys = 0;
+                for (int i = 0; i < keyCount(); i++) {
+                    if (stamp.contains(keys[i])) {
+                        validKeys++;
+                    }
+                }
+                if (validKeys == 0) {
+                    tool.addToWorkList(defaultSuccessor());
+                    ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessorIndex());
+                } else if (validKeys != keys.length) {
+                    ArrayList<BeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
+                    int[] newKeys = new int[validKeys];
+                    int[] newKeySuccessors = new int [validKeys + 1];
+                    double[] newKeyProbabilities = new double[validKeys + 1];
+                    double totalProbability = 0;
+                    int current = 0;
+                    for (int i = 0; i < keyCount() + 1; i++) {
+                        if (i == keyCount() || stamp.contains(keys[i])) {
+                            int index = newSuccessors.indexOf(keySuccessor(i));
+                            if (index == -1) {
+                                index = newSuccessors.size();
+                                newSuccessors.add(keySuccessor(i));
+                            }
+                            newKeySuccessors[current] = index;
+                            if (i < keyCount()) {
+                                newKeys[current] = keys[i];
+                            }
+                            newKeyProbabilities[current] = keyProbability(i);
+                            totalProbability += keyProbability(i);
+                            current++;
+                        }
+                    }
+                    if (totalProbability > 0) {
+                        for (int i = 0; i < current; i++) {
+                            newKeyProbabilities[i] /= totalProbability;
+                        }
+                    }
+
+                    for (int i = 0; i < blockSuccessorCount(); i++) {
+                        BeginNode successor = blockSuccessor(i);
+                        if (!newSuccessors.contains(successor)) {
+                            tool.deleteBranch(successor);
+                        }
+                        setBlockSuccessor(i, null);
+                    }
+
+                    BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
+                    IntegerSwitchNode newSwitch = graph().add(new IntegerSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
+                    ((FixedWithNextNode) predecessor()).setNext(newSwitch);
+                    GraphUtil.killWithUnusedFloatingInputs(this);
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LookupSwitchNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +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.graal.nodes.extended;
-
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * The {@code LookupSwitchNode} represents a lookup switch bytecode, which has a sorted
- * array of key values.
- */
-public final class LookupSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable {
-
-    private final int[] keys;
-
-    /**
-     * Constructs a new LookupSwitch instruction.
-     * @param value the instruction producing the value being switched on
-     * @param successors the list of successors
-     * @param keys the list of keys, sorted
-     */
-    public LookupSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] probability) {
-        super(value, successors, probability);
-        assert successors.length == keys.length + 1;
-        this.keys = keys;
-    }
-
-    public LookupSwitchNode(ValueNode value, int[] keys, double[] switchProbability) {
-        this(value, new BeginNode[switchProbability.length], keys, switchProbability);
-    }
-
-    /**
-     * Gets the key at the specified index.
-     * @param i the index
-     * @return the key at that index
-     */
-    public int keyAt(int i) {
-        return keys[i];
-    }
-
-    public int keysLength() {
-        return keys.length;
-    }
-
-    @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.emitLookupSwitch(this);
-    }
-
-    @Override
-    public void simplify(SimplifierTool tool) {
-        if (value() instanceof ConstantNode) {
-            ConstantNode constant = (ConstantNode) value();
-            int value = constant.value.asInt();
-
-            BeginNode remainingSux = (BeginNode) defaultSuccessor();
-            int remainingSuxIndex = blockSuccessorCount() - 1;
-            for (int i = 0; i < keys.length; i++) {
-                if (value == keys[i]) {
-                    remainingSux = blockSuccessor(i);
-                    remainingSuxIndex = i;
-                    break;
-                }
-            }
-
-            for (int i = 0; i < blockSuccessorCount(); i++) {
-                BeginNode sux = blockSuccessor(i);
-                if (sux != remainingSux) {
-                    tool.deleteBranch(sux);
-                }
-            }
-
-            tool.addToWorkList(remainingSux);
-            ((StructuredGraph) graph()).removeSplit(this, remainingSuxIndex);
-        }
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.max.cri.util.*;
+import com.oracle.max.criutils.*;
 
 /**
  * Creates a memory barrier.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -25,7 +25,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaType.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -44,7 +43,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -35,7 +34,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) graph();
         ValueNode guard = tool.createNullCheckGuard(object(), leafGraphId());
         ReadNode read = graph.add(new ReadNode(object(), location(), stamp()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -56,7 +55,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) graph();
         ValueNode guard = tool.createNullCheckGuard(object(), leafGraphId());
         WriteNode write = graph.add(new WriteNode(object(), value(), location()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -31,6 +33,8 @@
 public abstract class SwitchNode extends ControlSplitNode {
 
     @Input private ValueNode value;
+    private final double[] keyProbabilities;
+    private final int[] keySuccessors;
 
     public ValueNode value() {
         return value;
@@ -40,18 +44,73 @@
      * Constructs a new Switch.
      * @param value the instruction that provides the value to be switched over
      * @param successors the list of successors of this switch
-     * @param stateAfter the state after the switch
+     */
+    public SwitchNode(ValueNode value, BeginNode[] successors, double[] successorProbabilities, int[] keySuccessors, double[] keyProbabilities) {
+        super(StampFactory.forVoid(), successors, successorProbabilities);
+        assert keySuccessors.length == keyProbabilities.length;
+        this.value = value;
+        this.keySuccessors = keySuccessors;
+        this.keyProbabilities = keyProbabilities;
+    }
+
+    /**
+     * The number of distinct keys in this switch.
      */
-    public SwitchNode(ValueNode value, BeginNode[] successors, double[] probability) {
-        super(StampFactory.forVoid(), successors, probability);
-        this.value = value;
+    public abstract int keyCount();
+
+    /**
+     * The key at the specified position, encoded in a Constant.
+     */
+    public abstract Constant keyAt(int i);
+
+    /**
+     * Returns the index of the successor belonging to the key at the specified index.
+     */
+    public int keySuccessorIndex(int i) {
+        return keySuccessors[i];
+    }
+
+    /**
+     * Returns the successor for the key at the given index.
+     */
+    public BeginNode keySuccessor(int i) {
+        return blockSuccessor(keySuccessors[i]);
     }
 
     /**
-     * Gets the number of cases that this switch covers (excluding the default case).
-     * @return the number of cases
+     * Returns the probability of the key at the given index.
+     */
+    public double keyProbability(int i) {
+        return keyProbabilities[i];
+    }
+
+    /**
+     * Returns the index of the default (fall through) successor of this switch.
+     */
+    public int defaultSuccessorIndex() {
+        return keySuccessors[keySuccessors.length - 1];
+    }
+
+    /**
+     * Gets the successor corresponding to the default (fall through) case.
+     * @return the default successor
      */
-    public int numberOfCases() {
-        return blockSuccessorCount() - 1;
+    public BeginNode defaultSuccessor() {
+        if (defaultSuccessorIndex() == -1) {
+            throw new GraalInternalError("unexpected");
+        }
+        return defaultSuccessorIndex() == -1 ? null : blockSuccessor(defaultSuccessorIndex());
+    }
+
+    /**
+     * Helper function that sums up the probabilities of all keys that lead to a specific successor.
+     * @return an array of size successorCount with the accumulated probability for each successor.
+     */
+    public static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) {
+        double[] probability = new double[successorCount];
+        for (int i = 0; i < keySuccessors.length; i++) {
+            probability[keySuccessors[i]] += keyProbabilities[i];
+        }
+        return probability;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/TableSwitchNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +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.graal.nodes.extended;
-
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * The {@code TableSwitchNode} represents a table switch.
- */
-public final class TableSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable {
-
-    private final int lowKey;
-
-    /**
-     * Constructs a new TableSwitch instruction.
-     * @param value the instruction producing the value being switched on
-     * @param successors the list of successors
-     * @param lowKey the lowest integer key in the table
-     */
-    public TableSwitchNode(ValueNode value, BeginNode[] successors, int lowKey, double[] probability) {
-        super(value, successors, probability);
-        this.lowKey = lowKey;
-    }
-
-    public TableSwitchNode(ValueNode value, int lowKey, double[] switchProbability) {
-        this(value, new BeginNode[switchProbability.length], lowKey, switchProbability);
-    }
-
-    /**
-     * Gets the lowest key in the table switch (inclusive).
-     * @return the low key
-     */
-    public int lowKey() {
-        return lowKey;
-    }
-
-    /**
-     * Gets the highest key in the table switch (exclusive).
-     * @return the high key
-     */
-    public int highKey() {
-        return lowKey + numberOfCases();
-    }
-
-    @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.emitTableSwitch(this);
-    }
-
-    @Override
-    public void simplify(SimplifierTool tool) {
-        if (value() instanceof ConstantNode) {
-            ConstantNode constant = (ConstantNode) value();
-            int value = constant.value.asInt();
-
-            int remainingSuxIndex;
-            if (value >= lowKey() && value <= highKey()) {
-                remainingSuxIndex = value - lowKey();
-            } else {
-                remainingSuxIndex = blockSuccessorCount() - 1;
-            }
-
-            BeginNode remainingSux = blockSuccessor(remainingSuxIndex);
-            for (int i = 0; i < blockSuccessorCount(); i++) {
-                BeginNode sux = blockSuccessor(i);
-                if (sux != remainingSux) {
-                    tool.deleteBranch(sux);
-                }
-            }
-
-            tool.addToWorkList(remainingSux);
-            ((StructuredGraph) graph()).removeSplit(this, remainingSuxIndex);
-        }
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -71,7 +70,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -85,7 +84,14 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public boolean verify() {
+        assertTrue(storeKind != null, "UnsafeStoreNode must have a store kind");
+        assertTrue(object != null, "UnsafeStoreNode should have an object");
+        return super.verify();
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -38,7 +38,6 @@
 
     /**
      * Creates a new AccessArrayNode.
-     * @param kind the type of the result of this instruction
      * @param array the instruction that produces the array object value
      */
     public AccessArrayNode(Stamp stamp, ValueNode array) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -25,9 +25,7 @@
 import java.lang.reflect.*;
 import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -48,10 +46,8 @@
 
     /**
      * Constructs a new access field object.
-     * @param kind the result kind of the access
      * @param object the instruction producing the receiver object
      * @param field the compiler interface representation of the field
-     * @param graph
      */
     public AccessFieldNode(Stamp stamp, ValueNode object, ResolvedJavaField field, long leafGraphId) {
         super(stamp);
@@ -90,14 +86,14 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
     @Override
     public Map<Object, Object> getDebugProperties() {
         Map<Object, Object> debugProperties = super.getDebugProperties();
-        debugProperties.put("field", CodeUtil.format("%h.%n", field));
+        debugProperties.put("field", MetaUtil.format("%h.%n", field));
         return debugProperties;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -44,7 +44,7 @@
 
     /**
      * Create an new AccessIndexedNode.
-     * @param kind the result kind of the access
+     * @param stamp the result kind of the access
      * @param array the instruction producing the array
      * @param index the instruction producing the index
      * @param elementKind the type of the elements of the array
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.java;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.type.*;
@@ -37,9 +38,9 @@
  * locking hierarchy.
  * <br>
  * The Java bytecode specification allows non-balanced locking. Graal does not handle such cases and throws a
- * {@link CiBailout} instead. Detecting non-balanced monitors during bytecode parsing is difficult, since the
+ * {@link BailoutException} instead. Detecting non-balanced monitors during bytecode parsing is difficult, since the
  * node flowing into the {@link MonitorExitNode} can be a phi function hiding the node that was flowing into the
- * {@link MonitorEnterNode}. Optimization phases are free to throw {@link CiBailout} if they detect such cases.
+ * {@link MonitorEnterNode}. Optimization phases are free to throw {@link BailoutException} if they detect such cases.
  * Otherwise, they are detected during LIR construction.
  */
 public abstract class AccessMonitorNode extends AbstractStateSplit implements StateSplit, MemoryCheckpoint {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -63,7 +62,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -60,7 +59,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -77,7 +76,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/IsTypeNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/IsTypeNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -41,7 +41,7 @@
     /**
      * Constructs a new IsTypeNode.
      *
-     * @param object the instruction producing the object to check against the given type
+     * @param objectClass the instruction producing the object to check against the given type
      * @param type the type for this check
      */
     public IsTypeNode(ValueNode objectClass, ResolvedJavaType type) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -56,7 +55,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -25,7 +25,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -57,7 +56,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -49,10 +49,8 @@
 
     /**
      * Constructs a new NewMultiArrayNode.
-     * @param elementType the element type of the array
+     * @param type the element type of the array
      * @param dimensions the node which produce the dimensions for this array
-     * @param cpi the constant pool index for resolution
-     * @param riConstantPool the constant pool for resolution
      */
     public NewMultiArrayNode(ResolvedJavaType type, ValueNode[] dimensions) {
         super(StampFactory.exactNonNull(type));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -67,7 +66,7 @@
     }
 
     @Override
-    public void lower(CiLoweringTool tool) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,10 +22,15 @@
  */
 package com.oracle.graal.nodes.java;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.JavaType.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 /**
  * The {@code TypeSwitchNode} performs a lookup based on the type of the input value.
@@ -35,32 +40,116 @@
 
     private final ResolvedJavaType[] keys;
 
-    public TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] probability) {
-        super(value, successors, probability);
+    /**
+     * Constructs a type switch instruction. The keyProbabilities and keySuccessors array contain key.length + 1
+     * entries, the last entry describes the default (fall through) case.
+     *
+     * @param value the instruction producing the value being switched on
+     * @param successors the list of successors
+     * @param keys the list of types
+     * @param keyProbabilities the probabilities of the keys
+     * @param keySuccessors the successor index for each key
+     */
+    public TypeSwitchNode(ValueNode value, BeginNode[] successors, double[] successorProbabilities, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
+        super(value, successors, successorProbabilities, keySuccessors, keyProbabilities);
         assert successors.length == keys.length + 1;
-        assert successors.length == probability.length;
+        assert successors.length == keyProbabilities.length;
         this.keys = keys;
     }
 
-    public TypeSwitchNode(ValueNode value, ResolvedJavaType[] keys, double[] switchProbability) {
-        this(value, new BeginNode[switchProbability.length], keys, switchProbability);
-    }
-
-    public ResolvedJavaType keyAt(int i) {
-        return keys[i];
-    }
-
-    public int keysLength() {
+    @Override
+    public int keyCount() {
         return keys.length;
     }
 
     @Override
+    public Constant keyAt(int i) {
+        return keys[i].getEncoding(Representation.ObjectHub);
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitTypeSwitch(this);
+        gen.emitSwitch(this);
     }
 
     @Override
     public void simplify(SimplifierTool tool) {
-        // TODO(ls) perform simplifications based on the type of value
+        if (value() instanceof ConstantNode) {
+            Constant constant = value().asConstant();
+
+            int survivingEdge = keySuccessorIndex(keyCount());
+            for (int i = 0; i < keyCount(); i++) {
+                Constant typeHub = keyAt(i);
+                assert constant.kind == typeHub.kind;
+                if (tool.runtime().areConstantObjectsEqual(value().asConstant(), typeHub)) {
+                    survivingEdge = keySuccessorIndex(i);
+                }
+            }
+            for (int i = 0; i < blockSuccessorCount(); i++) {
+                if (i != survivingEdge) {
+                    tool.deleteBranch(blockSuccessor(i));
+                }
+            }
+            tool.addToWorkList(blockSuccessor(survivingEdge));
+            ((StructuredGraph) graph()).removeSplitPropagate(this, survivingEdge);
+        }
+        if (value() instanceof ReadHubNode) {
+            ObjectStamp stamp = ((ReadHubNode) value()).object().objectStamp();
+            if (stamp.type() != null) {
+                int validKeys = 0;
+                for (int i = 0; i < keyCount(); i++) {
+                    if (keys[i].isSubtypeOf(stamp.type())) {
+                        validKeys++;
+                    }
+                }
+                if (validKeys == 0) {
+                    tool.addToWorkList(defaultSuccessor());
+                    ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessorIndex());
+                } else if (validKeys != keys.length) {
+                    ArrayList<BeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
+                    ResolvedJavaType[] newKeys = new ResolvedJavaType[validKeys];
+                    int[] newKeySuccessors = new int [validKeys + 1];
+                    double[] newKeyProbabilities = new double[validKeys + 1];
+                    double totalProbability = 0;
+                    int current = 0;
+                    for (int i = 0; i < keyCount() + 1; i++) {
+                        if (i == keyCount() || keys[i].isSubtypeOf(stamp.type())) {
+                            int index = newSuccessors.indexOf(keySuccessor(i));
+                            if (index == -1) {
+                                index = newSuccessors.size();
+                                newSuccessors.add(keySuccessor(i));
+                            }
+                            newKeySuccessors[current] = index;
+                            if (i < keyCount()) {
+                                newKeys[current] = keys[i];
+                            }
+                            newKeyProbabilities[current] = keyProbability(i);
+                            totalProbability += keyProbability(i);
+                            current++;
+                        }
+                    }
+                    if (totalProbability > 0) {
+                        for (int i = 0; i < current; i++) {
+                            newKeyProbabilities[i] /= totalProbability;
+                        }
+                    }
+
+                    double[] newSuccessorProbabilities = successorProbabilites(newSuccessors.size(), newKeySuccessors, newKeyProbabilities);
+
+                    for (int i = 0; i < blockSuccessorCount(); i++) {
+                        BeginNode successor = blockSuccessor(i);
+                        if (!newSuccessors.contains(successor)) {
+                            tool.deleteBranch(successor);
+                        }
+                        setBlockSuccessor(i, null);
+                    }
+
+                    BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
+                    TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newSuccessorProbabilities, newKeys, newKeyProbabilities, newKeySuccessors));
+                    ((FixedWithNextNode) predecessor()).setNext(newSwitch);
+                    GraphUtil.killWithUnusedFloatingInputs(this);
+                }
+            }
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,43 @@
+/*
+ * 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.graal.nodes.spi;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Graal-specific extensions for the code cache provider interface.
+ */
+public interface GraalCodeCacheProvider extends CodeCacheProvider {
+
+    void lower(Node n, LoweringTool tool);
+
+    StructuredGraph intrinsicGraph(ResolvedJavaMethod caller, int bci, ResolvedJavaMethod method, List<? extends Node> parameters);
+
+    CompilationResult compile(ResolvedJavaMethod method, StructuredGraph graph);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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.nodes.spi;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+
+
+public interface GraphCache {
+
+    void put(StructuredGraph graph);
+
+    StructuredGraph get(ResolvedJavaMethod method);
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Tue Jul 03 11:16:56 2012 +0200
@@ -92,9 +92,7 @@
     public abstract void emitConditional(ConditionalNode i);
     public abstract void emitGuardCheck(BooleanNode comp, DeoptimizationReason deoptReason, DeoptimizationAction deoptAction, boolean negated, long leafGraphId);
 
-    public abstract void emitLookupSwitch(LookupSwitchNode i);
-    public abstract void emitTableSwitch(TableSwitchNode i);
-    public abstract void emitTypeSwitch(TypeSwitchNode i);
+    public abstract void emitSwitch(SwitchNode i);
 
     public abstract void emitInvoke(Invoke i);
     public abstract void emitRuntimeCall(RuntimeCallNode i);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java	Tue Jul 03 11:16:56 2012 +0200
@@ -22,9 +22,7 @@
  */
 package com.oracle.graal.nodes.spi;
 
-import com.oracle.graal.cri.*;
-
 public interface Lowerable {
 
-    void lower(CiLoweringTool tool);
+    void lower(LoweringTool tool);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.graal.nodes.spi;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+
+public interface LoweringTool {
+    GraalCodeCacheProvider getRuntime();
+    ValueNode getGuardAnchor();
+    ValueNode createNullCheckGuard(ValueNode object, long leafGraphId);
+    ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, long leafGraphId);
+    ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated, long leafGraphId);
+    Assumptions assumptions();
+}
+
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Tue Jul 03 11:16:56 2012 +0200
@@ -73,6 +73,14 @@
         return mask;
     }
 
+    public boolean isUnrestricted() {
+        return lowerBound == kind().minValue() && upperBound == kind().maxValue() && mask == defaultMask(kind());
+    }
+
+    public boolean contains(long value) {
+        return value >= lowerBound && value <= upperBound && (value & mask) == (value & defaultMask(kind()));
+    }
+
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Tue Jul 03 11:16:56 2012 +0200
@@ -47,7 +47,7 @@
         } else {
             // Normal control flow node.
             /* We do not take a successor snapshot because this iterator supports concurrent modifications
-             * as long as they do not change the size of the successor list. Not tasking a snapshot allows
+             * as long as they do not change the size of the successor list. Not taking a snapshot allows
              * us to see modifications to other branches that may happen while processing one branch.
              */
             for (Node successor : node.successors()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java	Tue Jul 03 11:16:56 2012 +0200
@@ -72,4 +72,14 @@
             closure.apply(this, value);
         }
     }
+
+    @Override
+    public boolean isPartOfThisState(VirtualState state) {
+        return this == state;
+    }
+
+    @Override
+    public void applyToVirtual(VirtualClosure closure) {
+        closure.apply(this);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.printer/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.printer</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Jul 03 11:16:56 2012 +0200
@@ -27,7 +27,6 @@
 import java.io.*;
 import java.util.*;
 
-import com.oracle.max.criutils.*;
 import com.oracle.graal.alloc.util.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -57,7 +56,7 @@
     /**
      * Creates a control flow graph printer.
      *
-     * @param buffer where the output generated via this printer shown be written
+     * @param out where the output generated via this printer shown be written
      */
     public CFGPrinter(OutputStream out) {
         super(out);
@@ -382,7 +381,7 @@
         StringBuilder buf = new StringBuilder();
         FrameState curState = state;
         do {
-            buf.append(CodeUtil.toLocation(curState.method(), curState.bci)).append('\n');
+            buf.append(MetaUtil.toLocation(curState.method(), curState.bci)).append('\n');
 
             if (curState.stackSize() > 0) {
                 buf.append("stack: ");
@@ -433,18 +432,21 @@
             LIRInstruction inst = lirInstructions.get(i);
             out.printf("nr %4d ", inst.id()).print(COLUMN_END);
 
-            if (inst.info != null) {
+            final StringBuilder stateString = new StringBuilder();
+            inst.forEachState(new LIRInstruction.StateProcedure() {
+                @Override
+                protected void doState(LIRFrameState state) {
+                    if (state.hasDebugInfo()) {
+                        stateString.append(debugInfoToString(state.debugInfo().getBytecodePosition(), state.debugInfo().getRegisterRefMap(), state.debugInfo().getFrameRefMap(), target.arch));
+                    } else {
+                        stateString.append(debugInfoToString(state.topFrame, null, null, target.arch));
+                    }
+                }
+            });
+            if (stateString.length() > 0) {
                 int level = out.indentationLevel();
                 out.adjustIndentation(-level);
-                String state;
-                if (inst.info.hasDebugInfo()) {
-                    state = debugInfoToString(inst.info.debugInfo().getBytecodePosition(), inst.info.debugInfo().getRegisterRefMap(), inst.info.debugInfo().getFrameRefMap(), target.arch);
-                } else {
-                    state = debugInfoToString(inst.info.topFrame, null, null, target.arch);
-                }
-                if (state != null) {
-                    out.print(" st ").print(HOVER_START).print("st").print(HOVER_SEP).print(state).print(HOVER_END).print(COLUMN_END);
-                }
+                out.print(" st ").print(HOVER_START).print("st").print(HOVER_SEP).print(stateString.toString()).print(HOVER_END).print(COLUMN_END);
                 out.adjustIndentation(level);
             }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,208 @@
+/*
+ * 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.graal.printer;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.max.criutils.*;
+
+/**
+ * Utility for printing compilation related data structures at various compilation phases.
+ * The output format is such that it can then be fed to the
+ * <a href="https://c1visualizer.dev.java.net/">C1 Visualizer</a>.
+ */
+public class CompilationPrinter {
+    public static final String COLUMN_END = " <|@";
+    public static final String HOVER_START = "<@";
+    public static final String HOVER_SEP = "|@";
+    public static final String HOVER_END = ">@";
+
+    private static OutputStream globalOut;
+
+    /**
+     * Gets a global output stream on a file in the current working directory.
+     * This stream is first opened if necessary. The name of the file
+     * is {@code "compilations-" + System.currentTimeMillis() + ".cfg"}.
+     *
+     * @return the global output stream or {@code null} if there was an error opening the file for writing
+     */
+    public static synchronized OutputStream globalOut() {
+        if (globalOut == null) {
+            File file = new File("compilations-" + System.currentTimeMillis() + ".cfg");
+            try {
+                globalOut = new FileOutputStream(file);
+            } catch (FileNotFoundException e) {
+                TTY.println("WARNING: Could not open " + file.getAbsolutePath());
+            }
+        }
+        return globalOut;
+    }
+
+    protected final LogStream out;
+
+    /**
+     * Creates a control flow graph printer.
+     *
+     * @param os where the output generated via this printer will be sent
+     */
+    public CompilationPrinter(OutputStream os) {
+        out = new LogStream(os);
+    }
+
+    /**
+     * Flushes all buffered output to the underlying output stream.
+     */
+    public void flush() {
+        out.flush();
+    }
+
+    protected void begin(String string) {
+        out.println("begin_" + string);
+        out.adjustIndentation(2);
+    }
+
+    protected void end(String string) {
+        out.adjustIndentation(-2);
+        out.println("end_" + string);
+    }
+
+    /**
+     * Prints a compilation timestamp for a given method.
+     *
+     * @param method the method for which a timestamp will be printed
+     */
+    public void printCompilation(JavaMethod method) {
+        begin("compilation");
+        out.print("name \" ").print(MetaUtil.format("%H::%n", method)).println('"');
+        out.print("method \"").print(MetaUtil.format("%f %r %H.%n(%p)", method)).println('"');
+        out.print("date ").println(System.currentTimeMillis());
+        end("compilation");
+    }
+
+    /**
+     * Formats given debug info as a multi line string.
+     */
+    protected String debugInfoToString(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap, Architecture arch) {
+        StringBuilder sb = new StringBuilder();
+
+        if (registerRefMap != null) {
+            sb.append("reg-ref-map:");
+            for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 1)) {
+                sb.append(' ').append(arch == null ? "r" + reg : arch.registers[reg]);
+            }
+            sb.append("\n");
+        }
+
+        if (frameRefMap != null) {
+            sb.append("frame-ref-map:");
+            for (int reg = frameRefMap.nextSetBit(0); reg >= 0; reg = frameRefMap.nextSetBit(reg + 1)) {
+                sb.append(' ').append("s").append(reg);
+            }
+            sb.append("\n");
+        }
+
+        if (codePos != null) {
+            BytecodePosition curCodePos = codePos;
+            List<VirtualObject> virtualObjects = new ArrayList<>();
+            do {
+                sb.append(MetaUtil.toLocation(curCodePos.getMethod(), curCodePos.getBCI()));
+                sb.append('\n');
+                if (curCodePos instanceof BytecodeFrame) {
+                    BytecodeFrame frame = (BytecodeFrame) curCodePos;
+                    if (frame.numStack > 0) {
+                        sb.append("stack: ");
+                        for (int i = 0; i < frame.numStack; i++) {
+                            sb.append(valueToString(frame.getStackValue(i), virtualObjects)).append(' ');
+                        }
+                        sb.append("\n");
+                    }
+                    sb.append("locals: ");
+                    for (int i = 0; i < frame.numLocals; i++) {
+                        sb.append(valueToString(frame.getLocalValue(i), virtualObjects)).append(' ');
+                    }
+                    sb.append("\n");
+                    if (frame.numLocks > 0) {
+                        sb.append("locks: ");
+                        for (int i = 0; i < frame.numLocks; ++i) {
+                            sb.append(valueToString(frame.getLockValue(i), virtualObjects)).append(' ');
+                        }
+                        sb.append("\n");
+                    }
+
+                }
+                curCodePos = curCodePos.getCaller();
+            } while (curCodePos != null);
+
+            for (int i = 0; i < virtualObjects.size(); i++) {
+                VirtualObject obj = virtualObjects.get(i);
+                sb.append(obj).append(" ").append(obj.type().name()).append(" ");
+                for (int j = 0; j < obj.values().length; j++) {
+                    sb.append(valueToString(obj.values()[j], virtualObjects)).append(' ');
+                }
+                sb.append("\n");
+
+            }
+        }
+        return sb.toString();
+    }
+
+    protected String valueToString(Value value, List<VirtualObject> virtualObjects) {
+        if (value == null) {
+            return "-";
+        }
+        if (isVirtualObject(value) && !virtualObjects.contains(asVirtualObject(value))) {
+            virtualObjects.add(asVirtualObject(value));
+        }
+        return value.toString();
+    }
+
+    public void printMachineCode(String code, String label) {
+        if (code.length() == 0) {
+            return;
+        }
+        if (label != null) {
+            begin("cfg");
+            out.print("name \"").print(label).println('"');
+            end("cfg");
+        }
+        begin("nmethod");
+        out.print(code);
+        out.println(" <|@");
+        end("nmethod");
+    }
+
+    public void printBytecodes(String code) {
+        if (code.length() == 0) {
+            return;
+        }
+        begin("bytecodes");
+        out.print(code);
+        out.println(" <|@");
+        end("bytecodes");
+    }
+}
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinterDumpHandler.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinterDumpHandler.java	Tue Jul 03 11:16:56 2012 +0200
@@ -27,7 +27,6 @@
 import java.util.*;
 
 import com.oracle.max.criutils.*;
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
@@ -150,7 +149,7 @@
         for (Object o : Debug.context()) {
             if (o instanceof ResolvedJavaMethod) {
                 ResolvedJavaMethod method = (ResolvedJavaMethod) o;
-                result.add(CodeUtil.format("%H::%n(%p)", method));
+                result.add(MetaUtil.format("%H::%n(%p)", method));
             } else if (o instanceof DebugDumpScope) {
                 DebugDumpScope debugDumpScope = (DebugDumpScope) o;
                 if (debugDumpScope.decorator && !result.isEmpty()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.snippets.test</code> project.
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.snippets</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Tue Jul 03 11:16:56 2012 +0200
@@ -31,13 +31,13 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.util.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.snippets.Snippet.InliningPolicy;
 
 /**
@@ -45,7 +45,7 @@
  */
 public class SnippetInstaller {
 
-    private final ExtendedRiRuntime runtime;
+    private final GraalCodeCacheProvider runtime;
     private final TargetDescription target;
     private final BoxingMethodPool pool;
 
@@ -57,7 +57,7 @@
      */
     private final Map<ResolvedJavaMethod, StructuredGraph> graphCache;
 
-    public SnippetInstaller(ExtendedRiRuntime runtime, TargetDescription target) {
+    public SnippetInstaller(GraalCodeCacheProvider runtime, TargetDescription target) {
         this.runtime = runtime;
         this.target = target;
         this.pool = new BoxingMethodPool(runtime);
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java	Tue Jul 03 11:16:56 2012 +0200
@@ -60,7 +60,7 @@
         if (intrinsic != null) {
             assert target.getAnnotation(Fold.class) == null;
 
-            Class< ? >[] parameterTypes = CodeUtil.signatureToTypes(target.signature(), target.holder());
+            Class< ? >[] parameterTypes = MetaUtil.signatureToTypes(target.signature(), target.holder());
 
             // Prepare the arguments for the reflective constructor call on the node class.
             Object[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false);
@@ -76,7 +76,7 @@
             // Clean up checkcast instructions inserted by javac if the return type is generic.
             cleanUpReturnCheckCast(newInstance);
         } else if (target.getAnnotation(Fold.class) != null) {
-            Class< ? >[] parameterTypes = CodeUtil.signatureToTypes(target.signature(), target.holder());
+            Class< ? >[] parameterTypes = MetaUtil.signatureToTypes(target.signature(), target.holder());
 
             // Prepare the arguments for the reflective method call
             Object[] arguments = prepareArguments(invoke, parameterTypes, target, true);
@@ -118,7 +118,7 @@
                 parameterIndex--;
             }
             ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i));
-            if (folding || CodeUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) {
+            if (folding || MetaUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) {
                 assert argument instanceof ConstantNode : "parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.callTarget().targetMethod() + " at " + sourceLocation(invoke.node()) + ": " + argument;
                 ConstantNode constantNode = (ConstantNode) argument;
                 Constant constant = constantNode.asConstant();
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Tue Jul 03 11:16:56 2012 +0200
@@ -106,7 +106,7 @@
 
         @Override
         public String toString() {
-            return CodeUtil.format("%h.%n", method) + map.toString();
+            return MetaUtil.format("%h.%n", method) + map.toString();
         }
     }
 
@@ -192,7 +192,7 @@
         Parameter[] parameterAnnotations = new Parameter[parameterCount];
         ConstantNode[] placeholders = new ConstantNode[parameterCount];
         for (int i = 0; i < parameterCount; i++) {
-            ConstantParameter c = CodeUtil.getParameterAnnotation(ConstantParameter.class, i, method);
+            ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method);
             if (c != null) {
                 String name = c.value();
                 Object arg = key.get(name);
@@ -200,7 +200,7 @@
                 assert checkConstantArgument(method, signature, i, name, arg, kind);
                 replacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(Constant.forBoxed(kind, arg), runtime, snippetCopy));
             } else {
-                Parameter p = CodeUtil.getParameterAnnotation(Parameter.class, i, method);
+                Parameter p = MetaUtil.getParameterAnnotation(Parameter.class, i, method);
                 assert p != null : method + ": parameter " + i + " must be annotated with either @Constant or @Parameter";
                 String name = p.value();
                 if (p.multiple()) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java	Tue Jul 03 11:16:56 2012 +0200
@@ -66,12 +66,12 @@
         Variable result = gen.newVariable(kind());
         switch (operation()) {
             case ABS:   gen.append(new Op2Reg(DAND, result, input, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); break;
-            case SQRT:  gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.SQRT, result, input)); break;
-            case LOG:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.LOG, result, input)); break;
-            case LOG10: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.LOG10, result, input)); break;
-            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;
+            case SQRT:  gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SQRT, result, input)); break;
+            case LOG:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.LOG, result, input)); break;
+            case LOG10: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.LOG10, result, input)); break;
+            case SIN:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SIN, result, input)); break;
+            case COS:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.COS, result, input)); break;
+            case TAN:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.TAN, result, input)); break;
             default:    throw GraalInternalError.shouldNotReachHere();
         }
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java	Tue Jul 03 11:16:56 2012 +0200
@@ -24,32 +24,31 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 
-import java.util.*;
-
-import com.oracle.max.asm.target.amd64.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
 
 public class AMD64MathIntrinsicOp extends AMD64LIRInstruction {
-    public enum Opcode  {
+    public enum IntrinsicOpcode  {
         SQRT,
         SIN, COS, TAN,
         LOG, LOG10;
     }
 
-    public AMD64MathIntrinsicOp(Opcode opcode, Value result, Value input) {
-        super(opcode, new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+    @Opcode private final IntrinsicOpcode opcode;
+    @Def protected Value result;
+    @Use protected Value input;
+
+    public AMD64MathIntrinsicOp(IntrinsicOpcode opcode, Value result, Value input) {
+        this.opcode = opcode;
+        this.result = result;
+        this.input = input;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        Opcode opcode = (Opcode) code;
-        Value result = output(0);
-        Value input = input(0);
-
         switch (opcode) {
             case SQRT:  masm.sqrtsd(asDoubleReg(result), asDoubleReg(input)); break;
             case LOG:   masm.flog(asDoubleReg(result), asDoubleReg(input), false); break;
@@ -60,14 +59,4 @@
             default:    throw GraalInternalError.shouldNotReachHere();
         }
     }
-
-    @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();
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.tests/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.graal.tests</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java	Tue Jul 03 11:16:56 2012 +0200
@@ -66,8 +66,8 @@
             }
         }
 
-        final ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(method);
-        InstalledCode compiledMethod = getCode(riMethod, graph);
+        final ResolvedJavaMethod javaMethod = runtime.getResolvedJavaMethod(method);
+        InstalledCode compiledMethod = getCode(javaMethod, graph);
         try {
             Object result = compiledMethod.execute("1", "2", "3");
             Assert.assertEquals("1-2-3", result);
@@ -80,8 +80,8 @@
     public void test3() {
         Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
-        final ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(method);
-        InstalledCode compiledMethod = getCode(riMethod, graph);
+        final ResolvedJavaMethod javaMethod = runtime.getResolvedJavaMethod(method);
+        InstalledCode compiledMethod = getCode(javaMethod, graph);
         try {
             Object result = compiledMethod.executeVarargs("1", "2", "3");
             Assert.assertEquals("1 2 3", result);
@@ -94,8 +94,8 @@
     public void test4() {
         Method method = getMethod("testMethodVirtual");
         final StructuredGraph graph = parse(method);
-        final ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(method);
-        InstalledCode compiledMethod = getCode(riMethod, graph);
+        final ResolvedJavaMethod javaMethod = runtime.getResolvedJavaMethod(method);
+        InstalledCode compiledMethod = getCode(javaMethod, graph);
         try {
             f1 = "0";
             Object result = compiledMethod.executeVarargs(this, "1", "2", "3");
@@ -108,8 +108,8 @@
     @Test
     public void test2() throws NoSuchMethodException, SecurityException {
         Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class);
-        ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(method);
-        StructuredGraph graph = new StructuredGraph(riMethod);
+        ResolvedJavaMethod javaMethod = runtime.getResolvedJavaMethod(method);
+        StructuredGraph graph = new StructuredGraph(javaMethod);
         new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph);
         new CanonicalizerPhase(null, runtime, null).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
@@ -123,7 +123,7 @@
             }
         }
 
-        InstalledCode compiledMethod = getCode(riMethod, graph);
+        InstalledCode compiledMethod = getCode(javaMethod, graph);
         final CompilableObject compilableObject = new CompilableObjectImpl(0);
 
         Object result;
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java	Tue Jul 03 11:16:56 2012 +0200
@@ -35,13 +35,13 @@
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.compiler.schedule.*;
-import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.java.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 
 /**
  * Base class for Graal compiler unit tests. These are white box tests
@@ -61,11 +61,11 @@
  */
 public abstract class GraalCompilerTest {
 
-    protected final ExtendedRiRuntime runtime;
+    protected final GraalCodeCacheProvider runtime;
 
     public GraalCompilerTest() {
         Debug.enable();
-        this.runtime = Graal.getRuntime().getCapability(ExtendedRiRuntime.class);
+        this.runtime = Graal.getRuntime().getCapability(GraalCodeCacheProvider.class);
     }
 
     protected void assertEquals(StructuredGraph expected, StructuredGraph graph) {
@@ -127,7 +127,7 @@
         return result.toString();
     }
 
-    protected ExtendedRiRuntime runtime() {
+    protected GraalCodeCacheProvider runtime() {
         return runtime;
     }
 
@@ -248,8 +248,8 @@
      * Parses a Java method to produce a graph.
      */
     protected StructuredGraph parse(Method m) {
-        ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(m);
-        StructuredGraph graph = new StructuredGraph(riMethod);
+        ResolvedJavaMethod javaMethod = runtime.getResolvedJavaMethod(m);
+        StructuredGraph graph = new StructuredGraph(javaMethod);
         new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.ALL).apply(graph);
         return graph;
     }
@@ -258,8 +258,8 @@
      * Parses a Java method to produce a graph.
      */
     protected StructuredGraph parseProfiled(Method m) {
-        ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(m);
-        StructuredGraph graph = new StructuredGraph(riMethod);
+        ResolvedJavaMethod javaMethod = runtime.getResolvedJavaMethod(m);
+        StructuredGraph graph = new StructuredGraph(javaMethod);
         new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL).apply(graph);
         return graph;
     }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/cfg/SimpleCFGTest.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/cfg/SimpleCFGTest.java	Tue Jul 03 11:16:56 2012 +0200
@@ -43,7 +43,7 @@
         BeginNode falseBegin = graph.add(new BeginNode());
         falseBegin.setNext(falseEnd);
 
-        IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5));
+        IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5, graph.graphId()));
         graph.start().setNext(ifNode);
 
         MergeNode merge = graph.add(new MergeNode());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.asm/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.max.asm</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64.java	Tue Jul 03 11:16:56 2012 +0200
@@ -24,7 +24,7 @@
 
 import static com.oracle.graal.api.code.Register.RegisterFlag.*;
 import static com.oracle.graal.api.meta.Kind.*;
-import static com.oracle.max.cri.util.MemoryBarriers.*;
+import static com.oracle.max.criutils.MemoryBarriers.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.Register.*;
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java	Tue Jul 03 11:16:56 2012 +0200
@@ -25,7 +25,7 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.max.asm.NumUtil.*;
 import static com.oracle.max.asm.target.amd64.AMD64.*;
-import static com.oracle.max.cri.util.MemoryBarriers.*;
+import static com.oracle.max.criutils.MemoryBarriers.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -2185,8 +2185,8 @@
      * Creates prefix and the encoding of the lower 6 bits of the ModRM-Byte. It emits an operand prefix. If the given
      * operands exceed 3 bits, the 4th bit is encoded in the prefix.
      *
-     * @param regEnc the encoding of the register part of the ModRM-Byte
-     * @param rmEnc the encoding of the r/m part of the ModRM-Byte
+     * @param regEncoding the encoding of the register part of the ModRM-Byte
+     * @param rmEncoding the encoding of the r/m part of the ModRM-Byte
      * @return the lower 6 bits of the ModRM-Byte that should be emitted
      */
     private int prefixqAndEncode(int regEncoding, int rmEncoding) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.cri/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.max.cri</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/util/MemoryBarriers.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +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.cri.util;
-
-/**
- * Constants and intrinsic definition for memory barriers.
- *
- * The documentation for each constant is taken from Doug Lea's
- * <a href="http://gee.cs.oswego.edu/dl/jmm/cookbook.html">The JSR-133 Cookbook for Compiler Writers</a>.
- * <p>
- * The {@code JMM_*} constants capture the memory barriers necessary to implement the Java Memory Model
- * with respect to volatile field accesses. Their values are explained by this
- * comment from templateTable_i486.cpp in the HotSpot source code:
- * <pre>
- * Volatile variables demand their effects be made known to all CPU's in
- * order.  Store buffers on most chips allow reads & writes to reorder; the
- * JMM's ReadAfterWrite.java test fails in -Xint mode without some kind of
- * memory barrier (i.e., it's not sufficient that the interpreter does not
- * reorder volatile references, the hardware also must not reorder them).
- *
- * According to the new Java Memory Model (JMM):
- * (1) All volatiles are serialized wrt to each other.
- * ALSO reads & writes act as acquire & release, so:
- * (2) A read cannot let unrelated NON-volatile memory refs that happen after
- * the read float up to before the read.  It's OK for non-volatile memory refs
- * that happen before the volatile read to float down below it.
- * (3) Similarly, a volatile write cannot let unrelated NON-volatile memory refs
- * that happen BEFORE the write float down to after the write.  It's OK for
- * non-volatile memory refs that happen after the volatile write to float up
- * before it.
- *
- * We only put in barriers around volatile refs (they are expensive), not
- * _between_ memory refs (which would require us to track the flavor of the
- * previous memory refs).  Requirements (2) and (3) require some barriers
- * before volatile stores and after volatile loads.  These nearly cover
- * requirement (1) but miss the volatile-store-volatile-load case.  This final
- * case is placed after volatile-stores although it could just as well go
- * before volatile-loads.
- * </pre>
- */
-public class MemoryBarriers {
-
-    /**
-     * The sequence {@code Load1; LoadLoad; Load2} ensures that {@code Load1}'s data are loaded before data accessed
-     * by {@code Load2} and all subsequent load instructions are loaded. In general, explicit {@code LoadLoad}
-     * barriers are needed on processors that perform speculative loads and/or out-of-order processing in which
-     * waiting load instructions can bypass waiting stores. On processors that guarantee to always preserve load
-     * ordering, these barriers amount to no-ops.
-     */
-    public static final int LOAD_LOAD   = 0x0001;
-
-    /**
-     * The sequence {@code Load1; LoadStore; Store2} ensures that {@code Load1}'s data are loaded before all data
-     * associated with {@code Store2} and subsequent store instructions are flushed. {@code LoadStore} barriers are
-     * needed only on those out-of-order processors in which waiting store instructions can bypass loads.
-     */
-    public static final int LOAD_STORE  = 0x0002;
-
-    /**
-     * The sequence {@code Store1; StoreLoad; Load2} ensures that {@code Store1}'s data are made visible to other
-     * processors (i.e., flushed to main memory) before data accessed by {@code Load2} and all subsequent load
-     * instructions are loaded. {@code StoreLoad} barriers protect against a subsequent load incorrectly using
-     * {@code Store1}'s data value rather than that from a more recent store to the same location performed by a
-     * different processor. Because of this, on the processors discussed below, a {@code StoreLoad} is strictly
-     * necessary only for separating stores from subsequent loads of the same location(s) as were stored before the
-     * barrier. {@code StoreLoad} barriers are needed on nearly all recent multiprocessors, and are usually the most
-     * expensive kind. Part of the reason they are expensive is that they must disable mechanisms that ordinarily
-     * bypass cache to satisfy loads from write-buffers. This might be implemented by letting the buffer fully
-     * flush, among other possible stalls.
-     */
-    public static final int STORE_LOAD  = 0x0004;
-
-    /**
-     * The sequence {@code Store1; StoreStore; Store2} ensures that {@code Store1}'s data are visible to other
-     * processors (i.e., flushed to memory) before the data associated with {@code Store2} and all subsequent store
-     * instructions. In general, {@code StoreStore} barriers are needed on processors that do not otherwise
-     * guarantee strict ordering of flushes from write buffers and/or caches to other processors or main memory.
-     */
-    public static final int STORE_STORE = 0x0008;
-
-    public static final int JMM_PRE_VOLATILE_WRITE = LOAD_STORE | STORE_STORE;
-    public static final int JMM_POST_VOLATILE_WRITE = STORE_LOAD | STORE_STORE;
-    public static final int JMM_PRE_VOLATILE_READ = 0;
-    public static final int JMM_POST_VOLATILE_READ = LOAD_LOAD | LOAD_STORE;
-
-    public static String barriersString(int barriers) {
-        StringBuilder sb = new StringBuilder();
-        sb.append((barriers & LOAD_LOAD) != 0 ? "LOAD_LOAD " : "");
-        sb.append((barriers & LOAD_STORE) != 0 ? "LOAD_STORE " : "");
-        sb.append((barriers & STORE_LOAD) != 0 ? "STORE_LOAD " : "");
-        sb.append((barriers & STORE_STORE) != 0 ? "STORE_STORE " : "");
-        return sb.toString().trim();
-    }
-}
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/util/UnsignedMath.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +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.cri.util;
-
-/**
- * {@link INTRINSIC} method definitions for unsigned comparisons.
- * All methods have correct, but slow, standard Java implementations so that
- * they can be used with compilers not supporting the intrinsics.
- */
-public class UnsignedMath {
-    private static final long MASK = 0xffffffffL;
-
-    /**
-     * Unsigned comparison aboveThan for two numbers.
-     */
-    public static boolean aboveThan(int a, int b) {
-        return (a & MASK) > (b & MASK);
-    }
-
-    /**
-     * Unsigned comparison aboveOrEqual for two numbers.
-     */
-    public static boolean aboveOrEqual(int a, int b) {
-        return (a & MASK) >= (b & MASK);
-    }
-
-    /**
-     * Unsigned comparison belowThan for two numbers.
-     */
-    public static boolean belowThan(int a, int b) {
-        return (a & MASK) < (b & MASK);
-    }
-
-    /**
-     * Unsigned comparison belowOrEqual for two numbers.
-     */
-    public static boolean belowOrEqual(int a, int b) {
-        return (a & MASK) <= (b & MASK);
-    }
-
-    /**
-     * Unsigned comparison aboveThan for two numbers.
-     */
-    public static boolean aboveThan(long a, long b) {
-        return (a > b) ^ ((a < 0) != (b < 0));
-    }
-
-    /**
-     * Unsigned comparison aboveOrEqual for two numbers.
-     */
-    public static boolean aboveOrEqual(long a, long b) {
-        return (a >= b) ^ ((a < 0) != (b < 0));
-    }
-
-    /**
-     * Unsigned comparison belowThan for two numbers.
-     */
-    public static boolean belowThan(long a, long b) {
-        return (a < b) ^ ((a < 0) != (b < 0));
-    }
-
-    /**
-     * Unsigned comparison belowOrEqual for two numbers.
-     */
-    public static boolean belowOrEqual(long a, long b) {
-        return (a <= b) ^ ((a < 0) != (b < 0));
-    }
-}
-
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java	Tue Jul 03 11:16:56 2012 +0200
@@ -294,7 +294,7 @@
     /**
      * Represents an XIR instruction, characterized by an {@link XirOp operation}, a {@link Kind kind}, an optional {@link XirOperand result}, a variable number of {@link XirOperand arguments},
      * and some optional instruction-specific state. The {@link #x}, {@link #y} and {@link #z} methods are convenient ways to access the first, second and third
-     * arguments, respectively. Only the {@link XirOp#CallStub} and {@link XirOp#CallRuntime} instructions can have more than three arguments.
+     * arguments, respectively. Only {@link XirOp#CallRuntime} instructions can have more than three arguments.
      *
      */
     public static final class XirInstruction {
@@ -499,7 +499,7 @@
          */
         PointerCAS,
         /**
-         * Call the {@link RiMethod} defined by {@code extra}  with {@code args} and put the result in {@code r}.
+         * Call the {@link JavaMethod} defined by {@code extra}  with {@code args} and put the result in {@code r}.
          */
         CallRuntime,
         /**
@@ -786,7 +786,7 @@
     }
 
     /**
-     * Terminates the assembly, checking invariants, in particular that {@link resultOperand} is set, and setting {@link #finished} to {@code true}.
+     * Terminates the assembly, checking invariants, in particular that {@link #resultOperand} is set, and setting {@link #finished} to {@code true}.
      */
     private void end() {
         assert !finished : "template may only be finished once!";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.criutils/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+Documentation for the <code>com.oracle.max.criutils</code> project.
+
+</body>
+</html>
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/BaseProfilingInfo.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * 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.criutils;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-
-
-/**
- * Dummy profiling information in case that a method was not executed frequently enough so that
- * no profiling information does exist yet, or in case that the profiling information should not be used.
- */
-public final class BaseProfilingInfo implements ProfilingInfo {
-    private static final ProfilingInfo[] NO_PROFILING_INFO = new ProfilingInfo[] {
-        new BaseProfilingInfo(ExceptionSeen.TRUE),
-        new BaseProfilingInfo(ExceptionSeen.FALSE),
-        new BaseProfilingInfo(ExceptionSeen.NOT_SUPPORTED)
-    };
-
-    private final ExceptionSeen exceptionSeen;
-
-    BaseProfilingInfo(ExceptionSeen exceptionSeen) {
-        this.exceptionSeen = exceptionSeen;
-    }
-
-    @Override
-    public int codeSize() {
-        return 0;
-    }
-
-    @Override
-    public JavaTypeProfile getTypeProfile(int bci) {
-        return null;
-    }
-
-    @Override
-    public double getBranchTakenProbability(int bci) {
-        return -1;
-    }
-
-    @Override
-    public double[] getSwitchProbabilities(int bci) {
-        return null;
-    }
-
-    @Override
-    public ExceptionSeen getExceptionSeen(int bci) {
-        return exceptionSeen;
-    }
-
-    @Override
-    public int getExecutionCount(int bci) {
-        return -1;
-    }
-
-    public static ProfilingInfo get(ExceptionSeen exceptionSeen) {
-        return NO_PROFILING_INFO[exceptionSeen.ordinal()];
-    }
-
-    @Override
-    public int getDeoptimizationCount(DeoptimizationReason reason) {
-        return 0;
-    }
-
-    @Override
-    public String toString() {
-        return "BaseProfilingInfo<" + CodeUtil.profileToString(this, null, "; ") + ">";
-    }
-}
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/BaseUnresolvedField.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +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.criutils;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-
-/**
- * A implementation of {@link JavaField} for an unresolved field.
- */
-public class BaseUnresolvedField implements JavaField {
-
-    public final String name;
-    public final JavaType holder;
-    public final JavaType type;
-
-    public BaseUnresolvedField(JavaType holder, String name, JavaType type) {
-        this.name = name;
-        this.type = type;
-        this.holder = holder;
-    }
-
-    public String name() {
-        return name;
-    }
-
-    public JavaType type() {
-        return type;
-    }
-
-    public Kind kind() {
-        return type.kind();
-    }
-
-    public JavaType holder() {
-        return holder;
-    }
-
-    @Override
-    public int hashCode() {
-        return System.identityHashCode(this);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        return o == this;
-    }
-
-    /**
-     * Converts this compiler interface field to a string.
-     */
-    @Override
-    public String toString() {
-        return CodeUtil.format("%H.%n [unresolved]", this);
-    }
-}
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/BaseUnresolvedMethod.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +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.criutils;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-
-/**
- * A implementation of {@link JavaMethod} for an unresolved method.
- */
-public class BaseUnresolvedMethod implements JavaMethod {
-
-    public final String name;
-    public final JavaType holder;
-    public final Signature signature;
-
-    public BaseUnresolvedMethod(JavaType holder, String name, Signature signature) {
-        this.name = name;
-        this.holder = holder;
-        this.signature = signature;
-    }
-
-    public String name() {
-        return name;
-    }
-
-    public JavaType holder() {
-        return holder;
-    }
-
-    public Signature signature() {
-        return signature;
-    }
-
-    @Override
-    public int hashCode() {
-        return System.identityHashCode(this);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        return o == this;
-    }
-
-    @Override
-    public String toString() {
-        return CodeUtil.format("%H.%n(%p) [unresolved]", this);
-    }
-}
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/CompilationPrinter.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +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.criutils;
-
-import static com.oracle.graal.api.code.ValueUtil.*;
-
-import java.io.*;
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-
-/**
- * Utility for printing compilation related data structures at various compilation phases.
- * The output format is such that it can then be fed to the
- * <a href="https://c1visualizer.dev.java.net/">C1 Visualizer</a>.
- */
-public class CompilationPrinter {
-    public static final String COLUMN_END = " <|@";
-    public static final String HOVER_START = "<@";
-    public static final String HOVER_SEP = "|@";
-    public static final String HOVER_END = ">@";
-
-    private static OutputStream globalOut;
-
-    /**
-     * Gets a global output stream on a file in the current working directory.
-     * This stream is first opened if necessary. The name of the file
-     * is {@code "compilations-" + System.currentTimeMillis() + ".cfg"}.
-     *
-     * @return the global output stream or {@code null} if there was an error opening the file for writing
-     */
-    public static synchronized OutputStream globalOut() {
-        if (globalOut == null) {
-            File file = new File("compilations-" + System.currentTimeMillis() + ".cfg");
-            try {
-                globalOut = new FileOutputStream(file);
-            } catch (FileNotFoundException e) {
-                TTY.println("WARNING: Could not open " + file.getAbsolutePath());
-            }
-        }
-        return globalOut;
-    }
-
-    protected final LogStream out;
-
-    /**
-     * Creates a control flow graph printer.
-     *
-     * @param os where the output generated via this printer will be sent
-     */
-    public CompilationPrinter(OutputStream os) {
-        out = new LogStream(os);
-    }
-
-    /**
-     * Flushes all buffered output to the underlying output stream.
-     */
-    public void flush() {
-        out.flush();
-    }
-
-    protected void begin(String string) {
-        out.println("begin_" + string);
-        out.adjustIndentation(2);
-    }
-
-    protected void end(String string) {
-        out.adjustIndentation(-2);
-        out.println("end_" + string);
-    }
-
-    /**
-     * Prints a compilation timestamp for a given method.
-     *
-     * @param method the method for which a timestamp will be printed
-     */
-    public void printCompilation(JavaMethod method) {
-        begin("compilation");
-        out.print("name \" ").print(CodeUtil.format("%H::%n", method)).println('"');
-        out.print("method \"").print(CodeUtil.format("%f %r %H.%n(%p)", method)).println('"');
-        out.print("date ").println(System.currentTimeMillis());
-        end("compilation");
-    }
-
-    /**
-     * Formats a given {@linkplain FrameState JVM frame state} as a multi line string.
-     */
-    protected String debugInfoToString(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap, Architecture arch) {
-        StringBuilder sb = new StringBuilder();
-
-        if (registerRefMap != null) {
-            sb.append("reg-ref-map:");
-            for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 1)) {
-                sb.append(' ').append(arch == null ? "r" + reg : arch.registers[reg]);
-            }
-            sb.append("\n");
-        }
-
-        if (frameRefMap != null) {
-            sb.append("frame-ref-map:");
-            for (int reg = frameRefMap.nextSetBit(0); reg >= 0; reg = frameRefMap.nextSetBit(reg + 1)) {
-                sb.append(' ').append("s").append(reg);
-            }
-            sb.append("\n");
-        }
-
-        if (codePos != null) {
-            BytecodePosition curCodePos = codePos;
-            List<VirtualObject> virtualObjects = new ArrayList<>();
-            do {
-                sb.append(CodeUtil.toLocation(curCodePos.getMethod(), curCodePos.getBCI()));
-                sb.append('\n');
-                if (curCodePos instanceof BytecodeFrame) {
-                    BytecodeFrame frame = (BytecodeFrame) curCodePos;
-                    if (frame.numStack > 0) {
-                        sb.append("stack: ");
-                        for (int i = 0; i < frame.numStack; i++) {
-                            sb.append(valueToString(frame.getStackValue(i), virtualObjects)).append(' ');
-                        }
-                        sb.append("\n");
-                    }
-                    sb.append("locals: ");
-                    for (int i = 0; i < frame.numLocals; i++) {
-                        sb.append(valueToString(frame.getLocalValue(i), virtualObjects)).append(' ');
-                    }
-                    sb.append("\n");
-                    if (frame.numLocks > 0) {
-                        sb.append("locks: ");
-                        for (int i = 0; i < frame.numLocks; ++i) {
-                            sb.append(valueToString(frame.getLockValue(i), virtualObjects)).append(' ');
-                        }
-                        sb.append("\n");
-                    }
-
-                }
-                curCodePos = curCodePos.getCaller();
-            } while (curCodePos != null);
-
-            for (int i = 0; i < virtualObjects.size(); i++) {
-                VirtualObject obj = virtualObjects.get(i);
-                sb.append(obj).append(" ").append(obj.type().name()).append(" ");
-                for (int j = 0; j < obj.values().length; j++) {
-                    sb.append(valueToString(obj.values()[j], virtualObjects)).append(' ');
-                }
-                sb.append("\n");
-
-            }
-        }
-        return sb.toString();
-    }
-
-    protected String valueToString(Value value, List<VirtualObject> virtualObjects) {
-        if (value == null) {
-            return "-";
-        }
-        if (isVirtualObject(value) && !virtualObjects.contains(asVirtualObject(value))) {
-            virtualObjects.add(asVirtualObject(value));
-        }
-        return value.toString();
-    }
-
-    public void printMachineCode(String code, String label) {
-        if (code.length() == 0) {
-            return;
-        }
-        if (label != null) {
-            begin("cfg");
-            out.print("name \"").print(label).println('"');
-            end("cfg");
-        }
-        begin("nmethod");
-        out.print(code);
-        out.println(" <|@");
-        end("nmethod");
-    }
-
-    public void printBytecodes(String code) {
-        if (code.length() == 0) {
-            return;
-        }
-        begin("bytecodes");
-        out.print(code);
-        out.println(" <|@");
-        end("bytecodes");
-    }
-}
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/JniMangle.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2007, 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.criutils;
-
-import com.oracle.graal.api.meta.*;
-
-/**
- * A utility for mangling Java method name and signatures into C function names.
- *
- * @see "http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/design.html#wp615"
- */
-public final class JniMangle {
-
-    private JniMangle() {
-    }
-
-    /**
-     * Mangles a given string such that it can be represented as (part of) a valid C function name.
-     */
-    private static String mangle(String name) {
-        final StringBuilder mangledName = new StringBuilder(100);
-        final int length = name.length();
-        for (int i = 0; i < length; i++) {
-            final char ch = name.charAt(i);
-            if (isAlphaNumeric(ch)) {
-                mangledName.append(ch);
-            } else if (ch == '_') {
-                mangledName.append("_1");
-            } else if (ch == '.') {
-                mangledName.append("_");
-            } else if (ch == ';') {
-                mangledName.append("_2");
-            } else if (ch == '[') {
-                mangledName.append("_3");
-            } else {
-                mangledName.append(String.format("%04x", (int) ch));
-            }
-        }
-        return mangledName.toString();
-    }
-
-    /**
-     * The delimiter in the string returned by {@link #mangleMethod(TypeDescriptor, String, SignatureDescriptor, boolean)} separating
-     * the short mangled form from the suffix to be added to obtain the long mangled form.
-     */
-    public static final char LONG_NAME_DELIMITER = ' ';
-
-    /**
-     * Mangles a Java method to the symbol(s) to be used when binding it to a native function.
-     * If {@code signature} is {@code null}, then a non-qualified symbol is returned.
-     * Otherwise, a qualified symbol is returned. A qualified symbol has its non-qualified
-     * prefix separated from its qualifying suffix by {@link #LONG_NAME_DELIMITER} if
-     * {@code splitSuffix} is {@code true}.
-     *
-     * @param declaringClass a fully qualified class descriptor
-     * @param name a Java method name (not checked here for validity)
-     * @param signature if non-null, a method signature to include in the mangled name
-     * @param splitSuffix determines if {@link #LONG_NAME_DELIMITER} should be used as described above
-     * @return the symbol for the C function as described above
-     */
-    public static String mangleMethod(ResolvedJavaType declaringClass, String name, Signature signature, boolean splitSuffix) {
-        final StringBuilder result = new StringBuilder(100);
-        final String declaringClassName = MetaUtil.toJavaName(declaringClass);
-        result.append("Java_").append(mangle(declaringClassName)).append('_').append(mangle(name));
-        if (signature != null) {
-            if (splitSuffix) {
-                result.append(LONG_NAME_DELIMITER);
-            }
-            result.append("__");
-            final String sig = signature.asString();
-            final String parametersSignature = sig.substring(1, sig.lastIndexOf(')')).replace('/', '.').replace('$', '.');
-            result.append(mangle(parametersSignature));
-        }
-        return result.toString();
-    }
-
-    private static boolean isAlphaNumeric(char ch) {
-        return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9');
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/MemoryBarriers.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,114 @@
+/*
+ * 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.criutils;
+
+/**
+ * Constants and intrinsic definition for memory barriers.
+ *
+ * The documentation for each constant is taken from Doug Lea's
+ * <a href="http://gee.cs.oswego.edu/dl/jmm/cookbook.html">The JSR-133 Cookbook for Compiler Writers</a>.
+ * <p>
+ * The {@code JMM_*} constants capture the memory barriers necessary to implement the Java Memory Model
+ * with respect to volatile field accesses. Their values are explained by this
+ * comment from templateTable_i486.cpp in the HotSpot source code:
+ * <pre>
+ * Volatile variables demand their effects be made known to all CPU's in
+ * order.  Store buffers on most chips allow reads & writes to reorder; the
+ * JMM's ReadAfterWrite.java test fails in -Xint mode without some kind of
+ * memory barrier (i.e., it's not sufficient that the interpreter does not
+ * reorder volatile references, the hardware also must not reorder them).
+ *
+ * According to the new Java Memory Model (JMM):
+ * (1) All volatiles are serialized wrt to each other.
+ * ALSO reads & writes act as acquire & release, so:
+ * (2) A read cannot let unrelated NON-volatile memory refs that happen after
+ * the read float up to before the read.  It's OK for non-volatile memory refs
+ * that happen before the volatile read to float down below it.
+ * (3) Similarly, a volatile write cannot let unrelated NON-volatile memory refs
+ * that happen BEFORE the write float down to after the write.  It's OK for
+ * non-volatile memory refs that happen after the volatile write to float up
+ * before it.
+ *
+ * We only put in barriers around volatile refs (they are expensive), not
+ * _between_ memory refs (which would require us to track the flavor of the
+ * previous memory refs).  Requirements (2) and (3) require some barriers
+ * before volatile stores and after volatile loads.  These nearly cover
+ * requirement (1) but miss the volatile-store-volatile-load case.  This final
+ * case is placed after volatile-stores although it could just as well go
+ * before volatile-loads.
+ * </pre>
+ */
+public class MemoryBarriers {
+
+    /**
+     * The sequence {@code Load1; LoadLoad; Load2} ensures that {@code Load1}'s data are loaded before data accessed
+     * by {@code Load2} and all subsequent load instructions are loaded. In general, explicit {@code LoadLoad}
+     * barriers are needed on processors that perform speculative loads and/or out-of-order processing in which
+     * waiting load instructions can bypass waiting stores. On processors that guarantee to always preserve load
+     * ordering, these barriers amount to no-ops.
+     */
+    public static final int LOAD_LOAD   = 0x0001;
+
+    /**
+     * The sequence {@code Load1; LoadStore; Store2} ensures that {@code Load1}'s data are loaded before all data
+     * associated with {@code Store2} and subsequent store instructions are flushed. {@code LoadStore} barriers are
+     * needed only on those out-of-order processors in which waiting store instructions can bypass loads.
+     */
+    public static final int LOAD_STORE  = 0x0002;
+
+    /**
+     * The sequence {@code Store1; StoreLoad; Load2} ensures that {@code Store1}'s data are made visible to other
+     * processors (i.e., flushed to main memory) before data accessed by {@code Load2} and all subsequent load
+     * instructions are loaded. {@code StoreLoad} barriers protect against a subsequent load incorrectly using
+     * {@code Store1}'s data value rather than that from a more recent store to the same location performed by a
+     * different processor. Because of this, on the processors discussed below, a {@code StoreLoad} is strictly
+     * necessary only for separating stores from subsequent loads of the same location(s) as were stored before the
+     * barrier. {@code StoreLoad} barriers are needed on nearly all recent multiprocessors, and are usually the most
+     * expensive kind. Part of the reason they are expensive is that they must disable mechanisms that ordinarily
+     * bypass cache to satisfy loads from write-buffers. This might be implemented by letting the buffer fully
+     * flush, among other possible stalls.
+     */
+    public static final int STORE_LOAD  = 0x0004;
+
+    /**
+     * The sequence {@code Store1; StoreStore; Store2} ensures that {@code Store1}'s data are visible to other
+     * processors (i.e., flushed to memory) before the data associated with {@code Store2} and all subsequent store
+     * instructions. In general, {@code StoreStore} barriers are needed on processors that do not otherwise
+     * guarantee strict ordering of flushes from write buffers and/or caches to other processors or main memory.
+     */
+    public static final int STORE_STORE = 0x0008;
+
+    public static final int JMM_PRE_VOLATILE_WRITE = LOAD_STORE | STORE_STORE;
+    public static final int JMM_POST_VOLATILE_WRITE = STORE_LOAD | STORE_STORE;
+    public static final int JMM_PRE_VOLATILE_READ = 0;
+    public static final int JMM_POST_VOLATILE_READ = LOAD_LOAD | LOAD_STORE;
+
+    public static String barriersString(int barriers) {
+        StringBuilder sb = new StringBuilder();
+        sb.append((barriers & LOAD_LOAD) != 0 ? "LOAD_LOAD " : "");
+        sb.append((barriers & LOAD_STORE) != 0 ? "LOAD_STORE " : "");
+        sb.append((barriers & STORE_LOAD) != 0 ? "STORE_LOAD " : "");
+        sb.append((barriers & STORE_STORE) != 0 ? "STORE_STORE " : "");
+        return sb.toString().trim();
+    }
+}
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/SnapshotProfilingInfo.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*
- * 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.criutils;
-
-import java.io.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-
-/**
- * A profiling info snapshot that can be {@linkplain #save(File, File) saved} to
- * and {@linkplain #load(File, CodeCacheProvider) loaded} from a file.
- */
-public class SnapshotProfilingInfo implements ProfilingInfo, Serializable {
-
-    private static final long serialVersionUID = -5837615128782960391L;
-    private final double[] branchTaken;
-    private final double[][] switches;
-    private final JavaTypeProfile[] typeProfiles;
-    private final ExceptionSeen[] exceptions;
-    private final int[] executions;
-    private final int[] deopts;
-
-    public SnapshotProfilingInfo(ProfilingInfo other) {
-        int codeSize = other.codeSize();
-        branchTaken = new double[codeSize];
-        switches = new double[codeSize][];
-        typeProfiles = new JavaTypeProfile[codeSize];
-        exceptions = new ExceptionSeen[codeSize];
-        executions = new int[codeSize];
-        deopts = new int[DeoptimizationReason.values().length];
-
-        for (int bci = 0; bci < codeSize; bci++) {
-            executions[bci] = other.getExecutionCount(bci);
-            exceptions[bci] = other.getExceptionSeen(bci);
-            branchTaken[bci] = other.getBranchTakenProbability(bci);
-            switches[bci] = other.getSwitchProbabilities(bci);
-            typeProfiles[bci] = other.getTypeProfile(bci);
-        }
-        for (DeoptimizationReason reason: DeoptimizationReason.values()) {
-            deopts[reason.ordinal()] = other.getDeoptimizationCount(reason);
-        }
-    }
-
-    @Override
-    public int codeSize() {
-        return branchTaken.length;
-    }
-
-    public double getBranchTakenProbability(int bci) {
-        return bci < branchTaken.length ? branchTaken[bci] : -1D;
-    }
-    public double[] getSwitchProbabilities(int bci) {
-        return bci < switches.length ? switches[bci] : null;
-    }
-    public JavaTypeProfile getTypeProfile(int bci) {
-        return bci < typeProfiles.length ? typeProfiles[bci] : null;
-    }
-    public ExceptionSeen getExceptionSeen(int bci) {
-        return bci < exceptions.length ? exceptions[bci] : ExceptionSeen.NOT_SUPPORTED;
-    }
-    public int getExecutionCount(int bci) {
-        return bci < executions.length ? executions[bci] : -1;
-    }
-    public int getDeoptimizationCount(DeoptimizationReason reason) {
-        return deopts[reason.ordinal()];
-    }
-
-    @Override
-    public String toString() {
-        return CodeUtil.profileToString(this, null, "; ");
-    }
-
-    /**
-     * Deserializes a profile snapshot from a file.
-     *
-     * @param file a file created by {@link #save(File, File)}
-     * @param runtime the runtime used to resolve {@link ResolvedJavaType}s during deserialization
-     * @return
-     * @throws ClassNotFoundException
-     * @throws IOException
-     */
-    public static SnapshotProfilingInfo load(File file, CodeCacheProvider runtime) throws ClassNotFoundException, IOException {
-        SnapshotProfilingInfo.SnapshotObjectInputStream ois = new SnapshotObjectInputStream(new BufferedInputStream(new FileInputStream(file), (int) file.length()), runtime);
-        try {
-            return (SnapshotProfilingInfo) ois.readObject();
-        } finally {
-            ois.close();
-        }
-    }
-
-    /**
-     * Serializes this snapshot to a file.
-     *
-     * @param file the file to which this snapshot is serialized
-     * @param txtFile
-     * @throws IOException
-     */
-    public void save(File file, File txtFile) throws IOException {
-        SnapshotProfilingInfo.SnapshotObjectOutputStream oos = new SnapshotObjectOutputStream(new FileOutputStream(file));
-        try {
-            oos.writeObject(this);
-        } finally {
-            oos.close();
-        }
-        if (txtFile != null) {
-            PrintStream out = new PrintStream(txtFile);
-            try {
-                out.println(CodeUtil.profileToString(this, null, CodeUtil.NEW_LINE));
-            } finally {
-                out.close();
-            }
-        }
-    }
-
-    static class RiResolvedTypePlaceholder implements Serializable {
-        private static final long serialVersionUID = -5149982457010023916L;
-        final Class javaMirror;
-        public RiResolvedTypePlaceholder(Class javaMirror) {
-            this.javaMirror = javaMirror;
-        }
-    }
-
-    static class SnapshotObjectOutputStream extends ObjectOutputStream {
-        public SnapshotObjectOutputStream(OutputStream out) throws IOException {
-            super(out);
-            enableReplaceObject(true);
-        }
-
-        @Override
-        protected Object replaceObject(Object obj) throws IOException {
-            if (obj instanceof ResolvedJavaType) {
-                return new RiResolvedTypePlaceholder(((ResolvedJavaType) obj).toJava());
-            }
-            return obj;
-        }
-    }
-
-    static class SnapshotObjectInputStream extends ObjectInputStream {
-        private final CodeCacheProvider runtime;
-        public SnapshotObjectInputStream(InputStream in, CodeCacheProvider runtime) throws IOException {
-            super(in);
-            enableResolveObject(true);
-            this.runtime = runtime;
-        }
-
-        @Override
-        protected Object resolveObject(Object obj) throws IOException {
-            if (obj instanceof SnapshotProfilingInfo.RiResolvedTypePlaceholder) {
-                ResolvedJavaType type = runtime.getResolvedJavaType(((SnapshotProfilingInfo.RiResolvedTypePlaceholder) obj).javaMirror);
-                return type;
-            }
-            return obj;
-        }
-    }
-}
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/TTY.java	Tue Jul 03 11:16:38 2012 +0200
+++ b/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/TTY.java	Tue Jul 03 11:16:56 2012 +0200
@@ -42,7 +42,7 @@
 
         /**
          * Creates an object that will suppress {@link TTY} for the current thread if the given filter does not
-         * {@linkplain #matches(String, Object) match} the given object. To revert the suppression state to how it was
+         * match the given object. To revert the suppression state to how it was
          * before this call, the {@link #remove()} method must be called on the suppression object.
          *
          * @param filter the pattern for matching. If {@code null}, then the match is successful. If it starts with "~",
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/TypeCheckHints.java	Tue Jul 03 11:16:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * 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.criutils;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaTypeProfile.*;
-
-/**
- * Utility for deriving hint types for a type check instruction (e.g. checkcast or instanceof)
- * based on the target type of the check and any profiling information available for the instruction.
- */
-public class TypeCheckHints {
-
-    private static final ResolvedJavaType[] NO_TYPES = {};
-
-    /**
-     * If true, then {@link #types} contains the only possible type that could pass the type check
-     * because the target of the type check is a final class or has been speculated to be a final class.
-     */
-    public final boolean exact;
-
-    /**
-     * The most likely types that the type check instruction will see.
-     */
-    public final ResolvedJavaType[] types;
-
-    /**
-     * Derives hint information for use when generating the code for a type check instruction.
-     *
-     * @param type the target type of the type check
-     * @param profile the profiling information available for the instruction (if any)
-     * @param assumptions the object in which speculations are recorded. This is null if speculations are not supported.
-     * @param minHintHitProbability if the probability that the type check will hit one the profiled types (up to
-     *            {@code maxHints}) is below this value, then {@link #types} will be null
-     * @param maxHints the maximum length of {@link #types}
-     */
-    public TypeCheckHints(ResolvedJavaType type, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) {
-        if (type != null && isFinalClass(type)) {
-            types = new ResolvedJavaType[] {type};
-            exact = true;
-        } else {
-            ResolvedJavaType uniqueSubtype = type == null ? null : type.uniqueConcreteSubtype();
-            if (uniqueSubtype != null) {
-                types = new ResolvedJavaType[] {uniqueSubtype};
-                if (assumptions != null) {
-                    assumptions.recordConcreteSubtype(type, uniqueSubtype);
-                    exact = true;
-                } else {
-                    exact = false;
-                }
-            } else {
-                exact = false;
-                ResolvedJavaType[] hintTypes = NO_TYPES;
-                JavaTypeProfile typeProfile = profile;
-                if (typeProfile != null) {
-                    double notRecordedTypes = typeProfile.getNotRecordedProbability();
-                    ProfiledType[] ptypes = typeProfile.getTypes();
-                    if (notRecordedTypes < (1D - minHintHitProbability) && ptypes != null && ptypes.length > 0) {
-                        hintTypes = new ResolvedJavaType[ptypes.length];
-                        int hintCount = 0;
-                        double totalHintProbability = 0.0d;
-                        for (ProfiledType ptype : ptypes) {
-                            ResolvedJavaType hint = ptype.type;
-                            if (type != null && hint.isSubtypeOf(type)) {
-                                hintTypes[hintCount++] = hint;
-                                totalHintProbability += ptype.probability;
-                            }
-                        }
-                        if (totalHintProbability >= minHintHitProbability) {
-                            if (hintTypes.length != hintCount || hintCount > maxHints) {
-                                hintTypes = Arrays.copyOf(hintTypes, Math.min(maxHints, hintCount));
-                            }
-                        } else {
-                            hintTypes = NO_TYPES;
-                        }
-
-                    }
-                }
-                this.types = hintTypes;
-            }
-        }
-    }
-
-    public static boolean isFinalClass(ResolvedJavaType type) {
-        return Modifier.isFinal(type.accessFlags()) || (type.isArrayClass() && Modifier.isFinal(type.componentType().accessFlags()));
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/UnsignedMath.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,89 @@
+/*
+ * 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.criutils;
+
+/**
+ * Utilities for unsigned comparisons.
+ * All methods have correct, but slow, standard Java implementations so that
+ * they can be used with compilers not supporting the intrinsics.
+ */
+public class UnsignedMath {
+    private static final long MASK = 0xffffffffL;
+
+    /**
+     * Unsigned comparison aboveThan for two numbers.
+     */
+    public static boolean aboveThan(int a, int b) {
+        return (a & MASK) > (b & MASK);
+    }
+
+    /**
+     * Unsigned comparison aboveOrEqual for two numbers.
+     */
+    public static boolean aboveOrEqual(int a, int b) {
+        return (a & MASK) >= (b & MASK);
+    }
+
+    /**
+     * Unsigned comparison belowThan for two numbers.
+     */
+    public static boolean belowThan(int a, int b) {
+        return (a & MASK) < (b & MASK);
+    }
+
+    /**
+     * Unsigned comparison belowOrEqual for two numbers.
+     */
+    public static boolean belowOrEqual(int a, int b) {
+        return (a & MASK) <= (b & MASK);
+    }
+
+    /**
+     * Unsigned comparison aboveThan for two numbers.
+     */
+    public static boolean aboveThan(long a, long b) {
+        return (a > b) ^ ((a < 0) != (b < 0));
+    }
+
+    /**
+     * Unsigned comparison aboveOrEqual for two numbers.
+     */
+    public static boolean aboveOrEqual(long a, long b) {
+        return (a >= b) ^ ((a < 0) != (b < 0));
+    }
+
+    /**
+     * Unsigned comparison belowThan for two numbers.
+     */
+    public static boolean belowThan(long a, long b) {
+        return (a < b) ^ ((a < 0) != (b < 0));
+    }
+
+    /**
+     * Unsigned comparison belowOrEqual for two numbers.
+     */
+    public static boolean belowOrEqual(long a, long b) {
+        return (a <= b) ^ ((a < 0) != (b < 0));
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/overview.html	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+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.
+-->
+
+</head>
+<body>
+
+<a href="modules.svg" title="Click to enlarge"><img src="modules.jpg" width="400"/></a>
+<p>
+This document is the unified Javadoc for the Graal code base.
+The module dependency graph is shown above.
+Each node in the diagram is a link to the standalone Javadoc for the denoted module.
+<p>
+<a target="_top" href="http://openjdk.java.net/projects/graal/"><b>[go to the OpenJDK Graal project site]</b></a>
+
+</body>
+</html>
--- a/mx/commands.py	Tue Jul 03 11:16:38 2012 +0200
+++ b/mx/commands.py	Tue Jul 03 11:16:56 2012 +0200
@@ -37,7 +37,7 @@
 _graal_home = dirname(dirname(__file__))
 
 """ Used to distinguish an exported GraalVM (see 'mx export'). """
-_vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src')) 
+_vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src'))
 
 """ The VM that will be run by the 'vm' command: graal(default), client or server.
     This can be set via the global '--vm' option. """
@@ -73,7 +73,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
- 
+
 """
 
 def clean(args):
@@ -88,22 +88,22 @@
 
 def export(args):
     """create a GraalVM zip file for distribution"""
-    
+
     parser = ArgumentParser(prog='mx export');
     parser.add_argument('--omit-vm-build', action='store_false', dest='vmbuild', help='omit VM build step')
     parser.add_argument('--omit-dist-init', action='store_false', dest='distInit', help='omit class files and IDE configurations from distribution')
     parser.add_argument('zipfile', nargs=REMAINDER, metavar='zipfile')
 
     args = parser.parse_args(args)
-    
+
     tmp = tempfile.mkdtemp(prefix='tmp', dir=_graal_home)
     if args.vmbuild:
         # Make sure the product VM binary is up to date
         build(['product'])
-        
+
     mx.log('Copying Java sources and mx files...')
     mx.run(('hg archive -I graal -I mx -I mxtool -I mx.sh ' + tmp).split())
-    
+
     # Copy the GraalVM JDK
     mx.log('Copying GraalVM JDK...')
     src = _jdk()
@@ -123,11 +123,11 @@
         mx.run('mx build'.split(), cwd=tmp)
         mx.log('Creating IDE configurations...')
         mx.run('mx ideinit'.split(), cwd=tmp)
-        
+
     # clean up temp directory
     mx.log('Cleaning up...')
     shutil.rmtree(tmp)
-    
+
     mx.log('Created distribution in ' + zfName)
 
 def example(args):
@@ -140,7 +140,7 @@
     def run_example(verbose, project, mainClass):
         cp = mx.classpath(project)
         sharedArgs = ['-Xcomp', '-XX:CompileOnly=Main', mainClass]
-        
+
         res = []
         mx.log("=== Server VM ===")
         printArg = '-XX:+PrintCompilation' if verbose else '-XX:-PrintCompilation'
@@ -150,7 +150,7 @@
         res.append(vm(['-cp', cp, printArg, '-G:-Extend', '-G:-Inline'] + sharedArgs))
         mx.log("=== Graal VM with extensions ===")
         res.append(vm(['-cp', cp, printArg, '-G:+Extend', '-G:-Inline'] + sharedArgs))
-        
+
         if len([x for x in res if x != 0]) != 0:
             return 1
         return 0
@@ -173,7 +173,7 @@
 
 def dacapo(args):
     """run one or all DaCapo benchmarks
-    
+
     DaCapo options are distinguished from VM options by a '@' prefix.
     For example, '@-n @5' will pass '-n 5' to the
     DaCapo harness."""
@@ -196,52 +196,52 @@
                     del args[0]
                 else:
                     bm = args[0]
-                
+
                 del args[0]
                 if bm not in sanitycheck.dacapoSanityWarmup.keys():
                     mx.abort('unknown benchmark: ' + bm + '\nselect one of: ' + str(sanitycheck.dacapoSanityWarmup.keys()))
                 numTests[bm] = n
-    
-    if len(numTests) is 0:    
+
+    if len(numTests) is 0:
         for bench in sanitycheck.dacapoSanityWarmup.keys():
             numTests[bench] = 1
-    
+
     # Extract DaCapo options
     dacapoArgs = [(arg[1:]) for arg in args if arg.startswith('@')]
-    
-    # The remainder are VM options 
+
+    # The remainder are VM options
     vmOpts = [arg for arg in args if not arg.startswith('@')]
     vm = _vm
-    
+
     failed = []
     for (test, n) in numTests.items():
         if not sanitycheck.getDacapo(test, n, dacapoArgs).test(vm, opts=vmOpts):
             failed.append(test)
-    
+
     if len(failed) != 0:
         mx.abort('DaCapo failures: ' + str(failed))
-    
+
 def intro(args):
     """run a simple program and visualize its compilation in the Graal Visualizer"""
     # Start the visualizer in a separate thread
     t = Thread(target=gv, args=([[]]))
     t.start()
-    
+
     # Give visualizer time to start
     mx.log('Waiting 5 seconds for visualizer to start')
     time.sleep(5)
-    
+
     vm(['-G:Dump=', '-G:MethodFilter=greet', '-Xcomp', '-XX:CompileOnly=HelloWorld::greet', '-cp', mx.classpath('com.oracle.graal.examples')] + args + ['examples.HelloWorld'])
 
 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:
@@ -259,34 +259,34 @@
                     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:    
+
+    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 
+
+    # The remainder are VM options
     vmOpts = [arg for arg in args if not arg.startswith('@')]
     vm = _vm;
-    
+
     failed = []
     for (test, n) in numTests.items():
         if not sanitycheck.getScalaDacapo(test, n, dacapoArgs).test(vm, opts=vmOpts):
             failed.append(test)
-    
+
     if len(failed) != 0:
         mx.abort('Scala DaCapo failures: ' + str(failed))
 
 def _vmLibDirInJdk(jdk):
     """
-    Get the directory within a JDK where the server and client 
+    Get the directory within a JDK where the server and client
     subdirectories are located.
     """
     if platform.system() == 'Darwin':
@@ -322,13 +322,13 @@
                 if not exists(src):
                     mx.abort('Host JDK directory is missing: ' + src)
                 shutil.copytree(src, dst)
-                
+
             # Make a copy of the default VM so that this JDK can be
-            # reliably used as the bootstrap for a HotSpot build.                
+            # reliably used as the bootstrap for a HotSpot build.
             jvmCfg = _vmCfgInJdk(jdk)
             if not exists(jvmCfg):
                 mx.abort(jvmCfg + ' does not exist')
-                
+
             lines = []
             defaultVM = None
             with open(jvmCfg) as f:
@@ -343,11 +343,11 @@
 
             assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg
             shutil.copytree(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), defaultVM + '0'))
-            
+
             with open(jvmCfg, 'w') as f:
                 for line in lines:
                     f.write(line)
-                    
+
             # Install a copy of the disassembler library
             try:
                 hsdis([], copyToDir=_vmLibDirInJdk(jdk))
@@ -356,14 +356,14 @@
     else:
         if not exists(jdk):
             mx.abort('The ' + build + ' VM has not been created - run \'mx clean; mx build ' + build + '\'')
-    return jdk 
+    return jdk
 
 # run a command in the windows SDK Debug Shell
 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo={}):
     newLine = os.linesep
     STARTTOKEN = 'RUNINDEBUGSHELL_STARTSEQUENCE'
     ENDTOKEN = 'RUNINDEBUGSHELL_ENDSEQUENCE'
-    
+
     winSDK = mx.get_env('WIN_SDK', 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\')
 
     p = subprocess.Popen('cmd.exe /E:ON /V:ON /K ""' + winSDK + '/Bin/SetEnv.cmd" & echo ' + STARTTOKEN + '"', \
@@ -402,22 +402,22 @@
     if logFile:
         log.close()
     return ret
-    
+
 def jdkhome(args, vm=None):
     """prints the JDK directory selected for the 'vm' command"""
-    
+
     build = _vmbuild if _vmSourcesAvailable else 'product'
     print join(_graal_home, 'jdk' + mx.java().version, build)
 
 def build(args, vm=None):
     """build the VM binary
-    
+
     The global '--vm' option selects which VM to build. This command also
     compiles the Graal classes irrespective of what VM is being built.
     The optional last argument specifies what build level is to be used
     for the VM binary."""
-    
-    # Call mx.build to compile the Java sources        
+
+    # Call mx.build to compile the Java sources
     opts2 = mx.build(['--source', '1.7'] + args, parser=ArgumentParser(prog='mx build'))
 
     if not _vmSourcesAvailable or not opts2.native:
@@ -429,7 +429,7 @@
 
     if vm is None:
         vm = _vm
-        
+
     if vm == 'server':
         buildSuffix = ''
     elif vm == 'client':
@@ -437,7 +437,7 @@
     else:
         assert vm == 'graal', vm
         buildSuffix = 'graal'
-        
+
     for build in builds:
         if build == 'ide-build-target':
             build = os.environ.get('IDE_BUILD_TARGET', 'product')
@@ -446,16 +446,16 @@
                 continue
 
         jdk = _jdk(build, create=True)
-            
+
         vmDir = join(_vmLibDirInJdk(jdk), vm)
         if not exists(vmDir):
             mx.log('Creating VM directory in JDK7: ' + vmDir)
             os.makedirs(vmDir)
-    
+
         def filterXusage(line):
             if not 'Xusage.txt' in line:
                 sys.stderr.write(line + os.linesep)
-                
+
         # Check that the declaration of graal_projects in arguments.cpp is up to date
         argumentsCpp = join(_graal_home, 'src', 'share', 'vm', 'runtime', 'arguments.cpp')
         assert exists(argumentsCpp), 'File does not exist: ' + argumentsCpp
@@ -478,9 +478,9 @@
         # Check if a build really needs to be done
         timestampFile = join(vmDir, '.build-timestamp')
         if opts2.force or not exists(timestampFile):
-            mustBuild = True 
+            mustBuild = True
         else:
-            mustBuild = False 
+            mustBuild = False
             timestamp = os.path.getmtime(timestampFile)
             sources = []
             for d in ['src', 'make']:
@@ -493,7 +493,7 @@
                 if len(f) != 0 and os.path.getmtime(f) > timestamp:
                     mustBuild = True
                     break
-                    
+
         if not mustBuild:
             mx.log('[all files in src and make directories are older than ' + timestampFile[len(_graal_home) + 1:] + ' - skipping native build]')
             continue
@@ -510,11 +510,11 @@
             winCompileSuccess = re.compile(r"^Writing \.vcxproj file:")
             if not _runInDebugShell(winCompileCmd, _graal_home, compilelogfile, winCompileSuccess):
                 mx.log('Error executing create command')
-                return 
+                return
             winBuildCmd = 'msbuild ' + _graal_home + r'\build\vs-amd64\jvm.vcxproj /p:Configuration=' + project_config + ' /p:Platform=x64'
             if not _runInDebugShell(winBuildCmd, _graal_home, compilelogfile):
                 mx.log('Error building project')
-                return 
+                return
         else:
             cpus = multiprocessing.cpu_count()
             if build == 'debug':
@@ -525,18 +525,18 @@
             env.setdefault('HOTSPOT_BUILD_JOBS', str(cpus))
             env['ALT_BOOTDIR'] = jdk
             env.setdefault('INSTALL', 'y')
-            
+
             # Clear these 2 variables as having them set can cause very confusing build problems
             env.pop('LD_LIBRARY_PATH', None)
             env.pop('CLASSPATH', None)
-            
+
             mx.run([mx.gmake_cmd(), build + buildSuffix], cwd=join(_graal_home, 'make'), err=filterXusage)
-        
+
         jvmCfg = _vmCfgInJdk(jdk)
         found = False
         if not exists(jvmCfg):
             mx.abort(jvmCfg + ' does not exist')
-        
+
         prefix = '-' + vm
         vmKnown = prefix + ' KNOWN\n'
         lines = []
@@ -572,7 +572,7 @@
 
     if vm is None:
         vm = _vm
-        
+
     build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product'
     jdk = _jdk(build)
     mx.expand_project_in_args(args)
@@ -650,46 +650,46 @@
             if s in c:
                 return True
         return False
-    
+
     for p in mx.projects():
         if getattr(p, 'testHarness', None) == harnessName:
             classes = []
             _find_classes_with_annotations(classes, p, None, ['@Test'])
-        
+
             if len(pos) != 0:
                 classes = [c for c in classes if containsAny(c, pos)]
             if len(neg) != 0:
                 classes = [c for c in classes if not containsAny(c, neg)]
-            
+
             if len(classes) != 0:
                 mx.log('running tests in ' + p.name)
-                harness(p, vmArgs, classes)                
+                harness(p, vmArgs, classes)
 
 def unittest(args):
     """run the Graal Compiler Unit Tests in the GraalVM
-    
+
     If filters are supplied, only tests whose fully qualified name
     include a filter as a substring are run. Negative filters are
     those with a '-' prefix. VM args should have a @ prefix."""
-    
+
     def harness(p, vmArgs, classes):
         vm(['-XX:-BootstrapGraal', '-esa'] + vmArgs + ['-cp', mx.classpath(p.name), 'org.junit.runner.JUnitCore'] + classes)
     _run_tests(args, 'unittest', harness)
-    
+
 def jtt(args):
     """run the Java Tester Tests in the GraalVM
-    
+
     If filters are supplied, only tests whose fully qualified name
     include a filter as a substring are run. Negative filters are
     those with a '-' prefix. VM args should have a @ prefix."""
-    
+
     def harness(p, vmArgs, classes):
         vm(['-XX:-BootstrapGraal', '-XX:CompileOnly=com/oracle/graal/jtt', '-XX:CompileCommand=compileonly,java/lang/Object::<init>', '-XX:CompileCommand=quiet', '-Xcomp', '-esa'] + vmArgs + ['-cp', mx.classpath(p.name), 'org.junit.runner.JUnitCore'] + classes)
     _run_tests(args, 'jtt', harness)
-    
+
 def buildvms(args):
     """build one or more VMs in various configurations"""
-    
+
     parser = ArgumentParser(prog='mx buildvms');
     parser.add_argument('--vms', help='a comma separated list of VMs to build (default: server,client,graal)', default='server,client,graal')
     parser.add_argument('--builds', help='a comma separated list of build types (default: product,fastdebug,debug)', default='product,fastdebug,debug')
@@ -697,7 +697,7 @@
     args = parser.parse_args(args)
     vms = args.vms.split(',')
     builds = args.builds.split(',')
-    
+
     allStart = time.time()
     for v in vms:
         for vmbuild in builds:
@@ -717,7 +717,7 @@
 
     If this command exits with a 0 exit code, then the source code is in
     a state that would be accepted for integration into the main repository."""
-    
+
     class Task:
         def __init__(self, title):
             self.start = time.time()
@@ -736,7 +736,7 @@
             mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']')
             mx.abort(codeOrMessage)
             return self
-             
+
     parser = ArgumentParser(prog='mx gate');
     parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code')
     parser.add_argument('-n', '--omit-native-build', action='store_false', dest='buildNative', help='omit cleaning and building native code')
@@ -748,11 +748,11 @@
     global _vmbuild
     global _vm
     global _jacoco
-    
-    tasks = []             
+
+    tasks = []
     total = Task('Gate')
     try:
-        
+
         t = Task('Clean')
         cleanArgs = []
         if not args.buildNative:
@@ -761,48 +761,48 @@
             cleanArgs.append('--no-java')
         clean(cleanArgs)
         tasks.append(t.stop())
-        
+
         t = Task('BuildJava')
         build(['--no-native'])
         tasks.append(t.stop())
         for vmbuild in ['fastdebug', 'product']:
             _vmbuild = vmbuild
-            
+
             if args.buildNative:
                 t = Task('BuildHotSpotGraal:' + vmbuild)
                 buildvms(['--vms', 'graal', '--builds', vmbuild])
                 tasks.append(t.stop())
-            
+
             t = Task('BootstrapWithSystemAssertions:' + vmbuild)
             vm(['-esa', '-version'])
             tasks.append(t.stop())
-            
+
             if vmbuild == 'product' and args.jacocout is not None:
                 _jacoco = 'on'
-            
+
             t = Task('UnitTests:' + vmbuild)
             unittest([])
             tasks.append(t.stop())
-            
+
             if vmbuild == 'product' and args.jacocout is not None:
                 _jacoco = 'append'
-            
+
             t = Task('JavaTesterTests:' + vmbuild)
             jtt(['@-XX:CompileCommand=exclude,*::run*'] if vmbuild == 'product'  else [])
             tasks.append(t.stop())
-            
+
             if vmbuild == 'product' and args.jacocout is not None:
                 _jacoco = 'off'
-            
+
             for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild):
                 t = Task(str(test) + ':' + vmbuild)
                 if not test.test('graal'):
                     t.abort(test.name + ' Failed')
                 tasks.append(t.stop())
-        
+
         if args.jacocout is not None:
             jacocoreport([args.jacocout])
-        
+
         t = Task('BootstrapWithDeoptALot')
         vm(['-XX:+DeoptimizeALot', '-XX:+VerifyOops', '-version'], vmbuild='fastdebug')
         tasks.append(t.stop())
@@ -811,13 +811,13 @@
         if mx.checkstyle([]) != 0:
             t.abort('Checkstyle warnings were found')
         tasks.append(t.stop())
-    
+
         t = Task('Canonicalization Check')
         mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...'))
         if mx.canonicalizeprojects([]) != 0:
             t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.')
         tasks.append(t.stop())
-    
+
         t = Task('CleanAndBuildGraalVisualizer')
         mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-q', 'clean', 'build'])
         tasks.append(t.stop())
@@ -836,17 +836,17 @@
                     t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild)
                     dacapo(['pmd'])
                     tasks.append(t.stop())
-        
+
     except KeyboardInterrupt:
         total.abort(1)
-    
+
     except BaseException as e:
         import traceback
         traceback.print_exc()
         total.abort(str(e))
 
     total.stop()
-    
+
     mx.log('Gate task times:')
     for t in tasks:
         mx.log('  ' + str(t.duration) + '\t' + t.title)
@@ -860,7 +860,7 @@
         if not exists(join(_graal_home, 'visualizer', 'build.xml')):
             mx.log('[This initial execution may take a while as the NetBeans platform needs to be downloaded]')
         mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-l', fp.name, 'run'])
-    
+
 def igv(args):
     """run the Ideal Graph Visualizer"""
     with open(join(_graal_home, '.ideal_graph_visualizer.log'), 'w') as fp:
@@ -897,7 +897,7 @@
             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:
@@ -906,7 +906,7 @@
             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):
         benchmarks += sanitycheck.getBootstraps()
@@ -917,7 +917,7 @@
         specjvms = [a[12:] for a in args if a.startswith('specjvm2008:')]
         for specjvm in specjvms:
             benchmarks += [sanitycheck.getSPECjvm2008([specjvm], True, 120, 120)]
-    
+
     for test in benchmarks:
         for (group, res) in test.bench(vm).items():
             if not results.has_key(group):
@@ -927,10 +927,10 @@
     if resultFile:
         with open(resultFile, 'w') as f:
             f.write(json.dumps(results))
-    
+
 def specjvm2008(args):
     """run one or all SPECjvm2008 benchmarks
-    
+
     All options begining with - will be passed to the vm except for -ikv -wt and -it.
     Other options are supposed to be benchmark names and will be passed to SPECjvm2008."""
     benchArgs = [a for a in args if a[0] != '-']
@@ -962,7 +962,7 @@
         benchArgs.remove(args[itIdx+1])
     vm = _vm;
     sanitycheck.getSPECjvm2008(benchArgs, skipValid, wt, it).bench(vm, opts=vmArgs)
-    
+
 def hsdis(args, copyToDir=None):
     """downloads the hsdis library
 
@@ -977,7 +977,7 @@
         mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavor + "/" + lib])
     if copyToDir is not None and exists(copyToDir):
         shutil.copy(path, copyToDir)
-    
+
 def hcfdis(args):
     """disassembles HexCodeFiles embedded in text files
 
@@ -1000,7 +1000,144 @@
     elif len(args) > 1:
         mx.abort('jacocoreport takes only one argument : an output directory')
     mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out])
-    
+
+def _fix_overview_summary(path, topLink):
+    """
+    Processes an "overview-summary.html" generated by javadoc to put the complete
+    summary text above the Packages table.
+    """
+
+    # This uses scraping and so will break if the relevant content produced by javadoc changes in any way!
+    with open(path) as fp:
+        content = fp.read()
+
+    class Chunk:
+        def __init__(self, content, ldelim, rdelim):
+            lindex = content.find(ldelim)
+            rindex = content.find(rdelim)
+            self.ldelim = ldelim
+            self.rdelim = rdelim
+            if lindex != -1 and rindex != -1 and rindex > lindex:
+                self.text = content[lindex + len(ldelim):rindex]
+            else:
+                self.text = None
+
+        def replace(self, content, repl):
+            lindex = content.find(self.ldelim)
+            rindex = content.find(self.rdelim)
+            old = content[lindex:rindex + len(self.rdelim)]
+            return content.replace(old, repl)
+
+    chunk1 = Chunk(content, """<div class="header">
+<div class="subTitle">
+<div class="block">""", """</div>
+</div>
+<p>See: <a href="#overview_description">Description</a></p>
+</div>""")
+
+    chunk2 = Chunk(content, """<div class="footer"><a name="overview_description">
+<!--   -->
+</a>
+<div class="subTitle">
+<div class="block">""", """</div>
+</div>
+</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->""")
+
+    assert chunk1.text, 'Could not find header section in ' + path
+    assert chunk2.text, 'Could not find footer section in ' + path
+
+    content = chunk1.replace(content, '<div class="header"><div class="subTitle"><div class="block">' + topLink + chunk2.text +'</div></div></div>')
+    content = chunk2.replace(content, '')
+
+    with open(path, 'w') as fp:
+        fp.write(content)
+
+def site(args):
+    """creates a website containing javadoc and the project dependency graph"""
+
+    parser = ArgumentParser(prog='site')
+    parser.add_argument('-d', '--base', action='store', help='directory for generated site', required=True, metavar='<dir>')
+
+    args = parser.parse_args(args)
+
+    args.base = os.path.abspath(args.base)
+    tmpbase = tempfile.mkdtemp(prefix=basename(args.base) + '.', dir=dirname(args.base))
+    unified = join(tmpbase, 'all')
+
+    try:
+        # Create javadoc for each project
+        mx.javadoc(['--base', tmpbase])
+
+        # Create unified javadoc for all projects
+        mx.javadoc(['--base', tmpbase,
+                    '--unified',
+                    '--arg', '@-windowtitle', '--arg', '@Graal OpenJDK Project Documentation',
+                    '--arg', '@-doctitle', '--arg', '@Graal OpenJDK Project Documentation',
+                    '--arg', '@-overview', '--arg', '@' + join(_graal_home, 'graal', 'overview.html')])
+        os.rename(join(tmpbase, 'javadoc'), unified)
+
+        # Generate dependency graph with Graphviz
+        _, tmp = tempfile.mkstemp()
+        try:
+            svg = join(tmpbase, 'all', 'modules.svg')
+            jpg = join(tmpbase, 'all', 'modules.jpg')
+            with open(tmp, 'w') as fp:
+                print >> fp, 'digraph projects {'
+                print >> fp, 'rankdir=BT;'
+                print >> fp, 'size = "13,13";'
+                print >> fp, 'node [shape=rect, fontcolor="blue"];'
+                #print >> fp, 'edge [color="green"];'
+                for p in mx.projects():
+                    print >> fp, '"' + p.name + '" [URL = "../' + p.name + '/javadoc/index.html", target = "_top"]'
+                    for dep in p.canonical_deps():
+                        if mx.project(dep, False):
+                            print >> fp, '"' + p.name + '" -> "' + dep + '"'
+                depths = dict()
+                for p in mx.projects():
+                    d = p.max_depth()
+                    depths.setdefault(d, list()).append(p.name)
+                for d, names in depths.iteritems():
+                    print >> fp, '{ rank = same; "' + '"; "'.join(names) + '"; }'
+                print >> fp, '}'
+
+            mx.run(['dot', '-Tsvg', '-o' + svg, '-Tjpg', '-o' + jpg, tmp])
+
+        finally:
+            os.remove(tmp)
+
+        # Post-process generated SVG to remove title elements which most browsers
+        # render as redundant (and annoying) tooltips.
+        with open(svg, 'r') as fp:
+            content = fp.read()
+        content = re.sub('<title>.*</title>', '', content)
+        content = re.sub('xlink:title="[^"]*"', '', content)
+        with open(svg, 'w') as fp:
+            fp.write(content)
+
+        # Post-process generated overview-summary.html files
+        top = join(tmpbase, 'all', 'overview-summary.html')
+        for root, _, files in os.walk(tmpbase):
+            for f in files:
+                if f == 'overview-summary.html':
+                    path = join(root, f)
+                    topLink = ''
+                    if top != path:
+                        link = os.path.relpath(join(tmpbase, 'all', 'index.html'), dirname(path))
+                        topLink = '<p><a href="' + link + '", target="_top"><b>[return to the overall Graal documentation]</b></a></p>'
+                    _fix_overview_summary(path, topLink)
+
+
+        if exists(args.base):
+            shutil.rmtree(args.base)
+        shutil.move(tmpbase, args.base)
+
+        print 'Created website - root is ' + join(args.base, 'all', 'index.html')
+
+    finally:
+        if exists(tmpbase):
+            shutil.rmtree(tmpbase)
+
 def mx_init():
     _vmbuild = 'product'
     commands = {
@@ -1022,11 +1159,12 @@
         'unittest' : [unittest, '[filters...]'],
         'jtt' : [jtt, '[filters...]'],
         'jacocoreport' : [jacocoreport, '[output directory]'],
+        'site' : [site, '[-options]'],
         'vm': [vm, '[-options] class [args...]'],
         'vmg': [vmg, '[-options] class [args...]'],
         'vmfg': [vmfg, '[-options] class [args...]']
     }
-    
+
     mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append'])
 
     if (_vmSourcesAvailable):
@@ -1035,12 +1173,12 @@
         mx.add_argument('--debug', action='store_const', dest='vmbuild', const='debug', help='select the debug build of the VM')
         mx.add_argument('--fastdebug', action='store_const', dest='vmbuild', const='fastdebug', help='select the fast debug build of the VM')
         mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse')
-        
+
         commands.update({
             'export': [export, '[-options] [zipfile]'],
             'build': [build, '[-options] [product|debug|fastdebug]...']
         })
-    
+
     mx.commands.update(commands)
 
 def mx_post_parse_cmd_line(opts):
@@ -1051,7 +1189,7 @@
     major = int(parts[1])
     if not major >= 7:
         mx.abort('Requires Java version 1.7 or greater, got version ' + version)
-    
+
     if (_vmSourcesAvailable):
         if hasattr(opts, 'vm') and opts.vm is not None:
             global _vm
--- a/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Tue Jul 03 11:16:38 2012 +0200
+++ b/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Tue Jul 03 11:16:56 2012 +0200
@@ -54,7 +54,7 @@
 org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
 org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
 org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
 org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
 org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
 org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
@@ -66,7 +66,9 @@
 org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
 org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
 org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
 org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
 org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
 org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
 org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
--- a/mx/projects	Tue Jul 03 11:16:38 2012 +0200
+++ b/mx/projects	Tue Jul 03 11:16:56 2012 +0200
@@ -127,7 +127,7 @@
 # graal.nodes
 project@com.oracle.graal.nodes@subDir=graal
 project@com.oracle.graal.nodes@sourceDirs=src,test
-project@com.oracle.graal.nodes@dependencies=com.oracle.max.cri,com.oracle.graal.graph
+project@com.oracle.graal.nodes@dependencies=com.oracle.max.criutils,com.oracle.graal.graph
 project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.nodes@javaCompliance=1.7
 
--- a/mxtool/mx.py	Tue Jul 03 11:16:38 2012 +0200
+++ b/mxtool/mx.py	Tue Jul 03 11:16:56 2012 +0200
@@ -50,10 +50,10 @@
 
   commands.py
       Suite specific extensions to the commands available to mx.
-      This is only processed for the primary suite.
 
   includes
-      Other suites to be loaded. This is recursive.
+      Other suites to be loaded. This is recursive. Each
+      line in an includes file is a path to a suite directory.
 
   env
       A set of environment variable definitions. These override any
@@ -223,11 +223,17 @@
             if d == 1:
                 result.add(n)
 
-
         if len(result) == len(self.deps) and frozenset(self.deps) == result:
             return self.deps
         return result;
 
+    def max_depth(self):
+        """
+        Get the maximum canonical distance between this project and its most distant dependency.
+        """
+        distances = dict()
+        self._compute_max_dep_distances(self.name, distances, 0)
+        return max(distances.values())        
 
     def source_dirs(self):
         """
@@ -288,8 +294,8 @@
         self.primary = primary
         mxDir = join(dir, 'mx')
         self._load_env(mxDir)
-        if primary:
-            self._load_commands(mxDir)
+        self._load_commands(mxDir)
+        self._load_includes(mxDir)
 
     def _load_projects(self, mxDir):
         libsMap = dict()
@@ -360,8 +366,9 @@
         if exists(commands):
             # temporarily extend the Python path
             sys.path.insert(0, mxDir)
-
             mod = __import__('commands')
+            
+            sys.modules[join(mxDir, 'commands')] = sys.modules.pop('commands')
 
             # revert the Python path
             del sys.path[0]
@@ -379,7 +386,9 @@
         if exists(includes):
             with open(includes) as f:
                 for line in f:
-                    self.includes.append(expandvars_in_property(line.strip()))
+                    include = expandvars_in_property(line.strip())
+                    self.includes.append(include)
+                    _loadSuite(include, False)
 
     def _load_env(self, mxDir):
         e = join(mxDir, 'env')
@@ -393,9 +402,8 @@
 
     def _post_init(self, opts):
         mxDir = join(self.dir, 'mx')
-        self._load_includes(mxDir)
         self._load_projects(mxDir)
-        if self.mx_post_parse_cmd_line is not None:
+        if hasattr(self, 'mx_post_parse_cmd_line'):
             self.mx_post_parse_cmd_line(opts)
         for p in self.projects:
             existing = _projects.get(p.name)
@@ -1240,27 +1248,10 @@
         try:
             if jdtJar is None:
                 log('Compiling Java sources for {0} with javac...'.format(p.name))
-                errFilt = None
+                javacCmd = [java().javac, '-g', '-J-Xmx1g', '-source', args.compliance, '-classpath', cp, '-d', outputDir, '@' + argfile.name]
                 if not args.warnAPI:
-                    class Filter:
-                        """
-                        Class to errFilt the 'is Sun proprietary API and may be removed in a future release'
-                        warning when compiling the VM classes.
-
-                        """
-                        def __init__(self):
-                            self.c = 0
-
-                        def eat(self, line):
-                            if 'proprietary API' in line:
-                                self.c = 2
-                            elif self.c != 0:
-                                self.c -= 1
-                            else:
-                                log(line.rstrip())
-                    errFilt=Filter().eat
-
-                run([java().javac, '-g', '-J-Xmx1g', '-source', args.compliance, '-classpath', cp, '-d', outputDir, '@' + argfile.name], err=errFilt)
+                    javacCmd.append('-XDignore.symbol.file')
+                run(javacCmd)
             else:
                 log('Compiling Java sources for {0} with JDT...'.format(p.name))
                 jdtArgs = [java().java, '-Xmx1g', '-jar', jdtJar,
@@ -1499,7 +1490,6 @@
             print '"' + p.name + '"->"' + dep + '"'
     print '}'
 
-
 def _source_locator_memento(deps):
     slm = XMLDoc()
     slm.open('sourceLookupDirector')
@@ -1950,16 +1940,18 @@
     eclipseinit(args, suite)
     netbeansinit(args, suite)
 
-def javadoc(args):
+def javadoc(args, parser=None, docDir='javadoc', includeDeps=True):
     """generate javadoc for some/all Java projects"""
 
-    parser = ArgumentParser(prog='mx javadoc')
+    parser = ArgumentParser(prog='mx javadoc') if parser is None else parser
+    parser.add_argument('-d', '--base', action='store', help='base directory for output')
     parser.add_argument('--unified', action='store_true', help='put javadoc in a single directory instead of one per project')
     parser.add_argument('--force', action='store_true', help='(re)generate javadoc even if package-list file exists')
     parser.add_argument('--projects', action='store', help='comma separated projects to process (omit to process all projects)')
+    parser.add_argument('--Wapi', action='store_true', dest='warnAPI', help='show warnings about using internal APIs')
     parser.add_argument('--argfile', action='store', help='name of file containing extra javadoc options')
+    parser.add_argument('--arg', action='append', dest='extra_args', help='extra Javadoc arguments (e.g. --arg @-use)', metavar='@<arg>', default=[])
     parser.add_argument('-m', '--memory', action='store', help='-Xmx value to pass to underlying JVM')
-    parser.add_argument('--wiki', action='store_true', help='generate Confluence Wiki format for package-info.java files')
     parser.add_argument('--packages', action='store', help='comma separated packages to process (omit to process all packages)')
 
     args = parser.parse_args(args)
@@ -1969,32 +1961,18 @@
     if args.projects is not None:
         candidates = [project(name) for name in args.projects.split(',')]
 
-    # optionally restrict packages within a project (most useful for wiki)
+    # optionally restrict packages within a project
     packages = []
     if args.packages is not None:
         packages = [name for name in args.packages.split(',')]
 
-    # the WikiDoclet cannot see the -classpath argument passed to javadoc so we pass the
-    # full list of projects as an explicit argument, thereby enabling it to map classes
-    # to projects, which is needed to generate Wiki links to the source code.
-    # There is no virtue in running the doclet on dependent projects as there are
-    # no generated links between Wiki pages
-    docletArgs = []
-    if args.wiki:
-        docDir = 'wikidoc'
-        toolsDir = project('com.oracle.max.tools').output_dir()
-        baseDir = project('com.oracle.max.base').output_dir()
-        dp = os.pathsep.join([toolsDir, baseDir])
-        project_list = ','.join(p.name for p in sorted_deps())
-        docletArgs = ['-docletpath', dp, '-doclet', 'com.oracle.max.tools.javadoc.wiki.WikiDoclet', '-projects', project_list]
-    else:
-        docDir = 'javadoc'
+    def outDir(p):
+        if args.base is None:
+            return join(p.dir, docDir)
+        return join(args.base, p.name, docDir)
 
     def check_package_list(p):
-        if args.wiki:
-            return True
-        else:
-            return not exists(join(p.dir, docDir, 'package-list'))
+        return not exists(join(outDir(p), 'package-list'))
 
     def assess_candidate(p, projects):
         if p in projects:
@@ -2007,7 +1985,7 @@
     projects = []
     for p in candidates:
         if not p.native:
-            if not args.wiki:
+            if includeDeps:
                 deps = p.all_deps([], includeLibs=False, includeSelf=False)
                 for d in deps:
                     assess_candidate(d, projects)
@@ -2019,12 +1997,12 @@
         for sourceDir in sourceDirs:
             for root, _, files in os.walk(sourceDir):
                 if len([name for name in files if name.endswith('.java')]) != 0:
-                    pkg = root[len(sourceDir) + 1:].replace('/','.')
-                    if (len(packages) == 0) | (pkg in packages):
+                    pkg = root[len(sourceDir) + 1:].replace(os.sep,'.')
+                    if len(packages) == 0 or pkg in packages:
                         pkgs.add(pkg)
         return pkgs
 
-    extraArgs = []
+    extraArgs = [a.lstrip('@') for a in args.extra_args]
     if args.argfile is not None:
         extraArgs += ['@' + args.argfile]
     memory = '2g'
@@ -2034,20 +2012,44 @@
 
     if not args.unified:
         for p in projects:
+            # The project must be built to ensure javadoc can find class files for all referenced classes
+            build(['--no-native', '--projects', p.name])
+            
             pkgs = find_packages(p.source_dirs(), set())
             deps = p.all_deps([], includeLibs=False, includeSelf=False)
             links = ['-link', 'http://docs.oracle.com/javase/' + str(p.javaCompliance.value) + '/docs/api/']
-            out = join(p.dir, docDir)
+            out = outDir(p)
             for d in deps:
-                depOut = join(d.dir, docDir)
+                depOut = outDir(d)
                 links.append('-link')
                 links.append(os.path.relpath(depOut, out))
             cp = classpath(p.name, includeSelf=True)
             sp = os.pathsep.join(p.source_dirs())
+            overviewFile = join(p.dir, 'overview.html')
+            overview = []
+            if exists(overviewFile):
+                overview = ['-overview', overviewFile]
+            nowarnAPI = []
+            if not args.warnAPI:
+                nowarnAPI.append('-XDignore.symbol.file')
             log('Generating {2} for {0} in {1}'.format(p.name, out, docDir))
-            run([java().javadoc, memory, '-classpath', cp, '-quiet', '-d', out, '-sourcepath', sp] + docletArgs + links + extraArgs + list(pkgs))
+            run([java().javadoc, memory,
+                 '-windowtitle', p.name + ' javadoc',
+                 '-XDignore.symbol.file',
+                 '-classpath', cp,
+                 '-quiet',
+                 '-d', out,
+                 '-sourcepath', sp] +
+                 links +
+                 extraArgs +
+                 overview +
+                 nowarnAPI +
+                 list(pkgs))
             log('Generated {2} for {0} in {1}'.format(p.name, out, docDir))
     else:
+        # The projects must be built to ensure javadoc can find class files for all referenced classes
+        build(['--no-native'])
+        
         pkgs = set()
         sp = []
         names = []
@@ -2058,10 +2060,23 @@
 
         links = ['-link', 'http://docs.oracle.com/javase/' + str(_java.javaCompliance.value) + '/docs/api/']
         out = join(_mainSuite.dir, docDir)
+        if args.base is not None:
+            out = join(args.base, docDir)
         cp = classpath()
         sp = os.pathsep.join(sp)
+        nowarnAPI = []
+        if not args.warnAPI:
+            nowarnAPI.append('-XDignore.symbol.file')
         log('Generating {2} for {0} in {1}'.format(', '.join(names), out, docDir))
-        run([java().javadoc, memory, '-classpath', cp, '-quiet', '-d', out, '-sourcepath', sp] + docletArgs + links + extraArgs + list(pkgs))
+        run([java().javadoc, memory,
+             '-classpath', cp,
+             '-quiet',
+             '-d', out,
+             '-sourcepath', sp] +
+             links +
+             extraArgs +
+             nowarnAPI +
+             list(pkgs))
         log('Generated {2} for {0} in {1}'.format(', '.join(names), out, docDir))
 
 def findclass(args):
@@ -2132,11 +2147,27 @@
 
 _argParser = ArgParser()
 
+def _findPrimarySuite():
+    # try current working directory first
+    mxDir = join(os.getcwd(), 'mx')
+    if exists(mxDir) and isdir(mxDir):
+        return dirname(mxDir)
+
+    # now search path of my executable
+    me = sys.argv[0]
+    parent = dirname(me)
+    while parent:
+        mxDir = join(parent, 'mx')
+        if exists(mxDir) and isdir(mxDir):
+            return parent
+        parent = dirname(parent)
+    return None
+
 def main():
-    cwdMxDir = join(os.getcwd(), 'mx')
-    if exists(cwdMxDir) and isdir(cwdMxDir):
+    primarySuiteDir = _findPrimarySuite()
+    if primarySuiteDir:
         global _mainSuite
-        _mainSuite = _loadSuite(os.getcwd(), True)
+        _mainSuite = _loadSuite(primarySuiteDir, True)
 
     opts, commandAndArgs = _argParser._parse_cmd_line()
 
--- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Tue Jul 03 11:16:38 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Tue Jul 03 11:16:56 2012 +0200
@@ -40,5 +40,5 @@
 
 # Disable assertions for RequestProcessor to prevent annoying messages in case
 # of multiple SceneAnimator update tasks in the default RequestProcessor.
-run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx2g
+run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx4g
 debug.args.extra = -J-server -J-da:org.openide.util.RequestProcessor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/build.xml	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.oracle.graal.visualizer.logviewer" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.oracle.graal.visualizer.logviewer.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/manifest.mf	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.oracle.graal.visualizer.logviewer
+OpenIDE-Module-Layer: com/oracle/graal/visualizer/logviewer/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/logviewer/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/nbproject/build-impl.xml	Tue Jul 03 11:16:56 2012 +0200
@@ -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.logviewer-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/LogViewer/nbproject/genfiles.properties	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=979ec129
+build.xml.script.CRC32=1c914106
+build.xml.stylesheet.CRC32=a56c6a5b@2.47.2
+# 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=979ec129
+nbproject/build-impl.xml.script.CRC32=712ab216
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/nbproject/project.properties	Tue Jul 03 11:16:56 2012 +0200
@@ -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/LogViewer/nbproject/project.xml	Tue Jul 03 11:16:56 2012 +0200
@@ -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>com.oracle.graal.visualizer.logviewer</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.19.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.30.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.24.1</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.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.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.nodes</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.25.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.39.1</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages>
+                <package>com.oracle.graal.visualizer.logviewer</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/nbproject/suite.properties	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,1 @@
+com.oracle.graal.visualizer.logviewer.LogCompilationViewerFactory
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/Bundle.properties	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=LogViewer
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/LogCompilationViewer.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,51 @@
+/*
+ * 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.logviewer;
+
+import com.oracle.graal.visualizer.logviewer.scene.LogScene;
+import com.oracle.graal.visualizer.editor.CompilationViewer;
+import com.sun.hotspot.igv.data.InputGraph;
+import java.awt.Component;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+
+class LogCompilationViewer implements CompilationViewer {
+
+    private LogScene scene;
+
+    public LogCompilationViewer() {
+        this.scene = new LogScene();
+    }
+
+    @Override
+    public Lookup getLookup() {
+        return Lookups.fixed();
+    }
+
+    @Override
+    public Component getComponent() {
+        return scene;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/LogCompilationViewerFactory.java	Tue Jul 03 11:16:56 2012 +0200
@@ -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.logviewer;
+
+import com.oracle.graal.visualizer.editor.CompilationViewer;
+import com.oracle.graal.visualizer.editor.SplitCompilationViewerFactory;
+import com.sun.hotspot.igv.data.InputGraph;
+
+public class LogCompilationViewerFactory extends SplitCompilationViewerFactory {
+
+    @Override
+    public String getName() {
+        return "Log";
+    }
+
+    @Override
+    protected CompilationViewer createViewer(InputGraph graph) {
+        return new LogCompilationViewer();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/layer.xml	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,13 @@
+<?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="CompilationViewer">
+        <folder name="Log">
+            <folder name="Actions">
+                <file name="com-oracle-graal-visualizer-logviewer-scene-actions-ImportLogAction.shadow">
+                    <attr name="originalFile" stringvalue="Actions/File/com-oracle-graal-visualizer-logviewer-scene-actions-ImportLogActions.instance"/>
+                </file>
+            </folder>
+        </folder>
+    </folder>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogLine.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,91 @@
+/*
+ * 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.logviewer.model;
+
+public class LogLine {
+
+    private final int lineNum;
+	private final CharSequence text;
+	private final Method method;
+	private final Scope scope;
+	private final Node node;
+	
+	LogLine(int lineNum, CharSequence text, Method method, Scope scope, Node node) {
+		this.lineNum = lineNum;
+        this.text = text;
+		this.method = method;
+		this.scope = scope;
+		this.node = node;
+	}
+    
+    /**
+     * Returns the number of the line in the log file
+     * @return file line number
+     */
+    public int getLineNumber() {
+        return lineNum;
+    }
+	
+	/**
+	 * Returns the text of the log line
+	 * @return log line text
+	 */
+	public String getText() {
+		return text.toString();
+	}
+	
+	/**
+	 * Returns the parent method
+	 * @return the parent method
+	 */
+	public Method getMethod() {
+		return method;
+	}
+	
+	/**
+	 * Returns the parent scope
+	 * @return the parent scope
+	 */
+	public Scope getScope() {
+		return scope;
+	}
+	
+	/**
+	 * Returns the parent node
+	 * @return the parent node (or <code>null</code> if the log is not in a node's context)
+	 */
+	public Node getNode() {
+		return node;
+	}
+	
+	/**
+	 * The string representation of a log line is the text of it.
+	 */
+	@Override
+	public String toString() {
+		return getText();
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogModel.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,127 @@
+/*
+ * 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.logviewer.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+public class LogModel {
+
+	private List<Method> methods = new ArrayList<>();
+	private List<LogLine> logs = new ArrayList<>();
+	
+	void add(Method method) {
+		methods.add(method);
+	}
+	
+	/**
+	 * Returns a list of all methods within the log model.
+	 * @return list of methods
+	 */
+	public List<Method> getMethods() {
+		return Collections.unmodifiableList(methods);
+	}
+	
+	void add(LogLine log) {
+		logs.add(log);
+	}
+	
+	/**
+	 * Returns a list of all logs
+	 * @return list of log lines
+	 */
+	public List<LogLine> getLogs() {
+		return Collections.unmodifiableList(logs);
+	}
+	
+	/**
+	 * Returns a list of logs which are before and after a specific log line (and the line itself).
+	 * @param log reference log line
+	 * @param pre number of lines before the reference line
+	 * @param post number of lines after the reference line
+	 * @return list of log lines (size: pre + post + 1)
+	 */
+	public List<LogLine> range(LogLine log, int pre, int post) {
+		if(log == null) throw new NoSuchElementException();
+		
+		List<LogLine> logs = getLogs();
+		int index = logs.indexOf(log);
+		
+		if(index == -1) throw new NoSuchElementException();
+		
+		int fromIndex = index - pre;
+		int toIndex = index + post + 1;
+		
+		return getLogs().subList(fromIndex > 0 ? fromIndex : 0, toIndex < logs.size() ? toIndex : logs.size());
+	}
+	
+	/**
+	 * Returns a string with log l which are before and after a specific log line (and the line itself).
+	 * @param log reference log line
+	 * @param pre number of lines before the reference line
+	 * @param post number of lines after the reference line
+	 * @return list of log lines (size: pre + post + 1)
+	 */
+	public String rangeAsString(LogLine log, int pre, int post) {
+		List<LogLine> list = range(log, pre, post);
+		
+		String ls = System.getProperty("line.separator");
+		
+		boolean first = true;
+		StringBuilder buf = new StringBuilder();
+		for(LogLine line : list) {
+			if(!first) buf.append(ls);
+			else first = false;
+			
+			buf.append(line);
+		}
+		
+		return buf.toString();
+	}
+	
+	public LogLine getLogLine(int lineNum) {
+		int index = lineNum;
+		if(index >= logs.size()) index = logs.size()-1;
+		
+		LogLine logLine = logs.get(lineNum);
+		while(logLine.getLineNumber() > lineNum) {
+			logLine = logs.get(--index);
+		}
+		while(logLine.getLineNumber() < lineNum) {
+			logLine = logs.get(++index);
+		}
+		
+		return logLine;
+	}
+	
+	public List<LogLine> range(int lineNum, int pre, int post) {
+		LogLine logLine = getLogLine(lineNum);
+		return range(logLine, pre, post);
+	}
+	
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogParser.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,230 @@
+/*
+ * 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.logviewer.model;
+
+import com.oracle.graal.visualizer.logviewer.model.io.FileLine;
+import com.oracle.graal.visualizer.logviewer.model.io.ProgressMonitor;
+import com.oracle.graal.visualizer.logviewer.model.io.SeekableFile;
+import com.oracle.graal.visualizer.logviewer.model.io.SeekableFileReader;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class LogParser {
+	
+	private static final Pattern METHOD_PATTERN =
+		Pattern.compile("Finished target method HotSpotMethod<(.+?)>, isStub (true|false)");
+	private static final Pattern SCOPE_PATTERN =
+		Pattern.compile("scope: (.+?)");
+	private static final Pattern NODE_PATTERN =
+		Pattern.compile(".*?([0-9]+)\\|([0-9a-zA-Z.]+).*?");
+	
+	private final List<ParseErrorListener> errorListeners = new ArrayList<>();
+	private final List<ParseError> errors = new ArrayList<>();
+	
+	/**
+	 * Parses a log file without any feedback. When the parsing process is finished, the method returns a LogModel-object.
+	 * @param file log file
+	 * @return model-object
+	 * @throws IOException
+	 * @throws LogParserException
+	 */
+	public LogModel parse(File file) throws IOException {
+		return parse(file, null);
+	}
+	
+	/**
+	 * Parses a log file and uses a ProgressMonitor to give the caller a progress feedback. It returns a LogModel-object.
+	 * @param file log file
+	 * @param monitor monitor for progress monitoring (uses default gap)
+	 * @return model-object
+	 * @throws IOException
+	 * @throws LogParserException
+	 */
+	public LogModel parse(File file, ProgressMonitor monitor) throws IOException {
+		return parse(file, monitor, SeekableFileReader.DEFAULT_GAP);
+	} 
+	
+	/**
+	 * Parses a log file and uses a ProgressMonitor to give the caller a progress feedback. It returns a LogModel-object.
+	 * @param file log file
+	 * @param monitor monitor for progress monitoring (uses custom gap)
+	 * @param gap custom gap (every x bytes read from the file, the monitor will be informed)
+	 * @return model-object
+	 * @throws IOException
+	 * @throws LogParserException
+	 */
+	public LogModel parse(File file, ProgressMonitor monitor, int gap) throws IOException {
+		errors.clear();
+		SeekableFileReader reader = new SeekableFileReader(file, monitor, gap);
+		SeekableFile seekableFile = reader.getSeekableFile();
+		BufferedReader r = new BufferedReader(reader);
+		
+		LogModel model = new LogModel();
+		Method currentMethod = new Method(model);
+		Scope currentScope = null;
+		
+		Matcher matcher;
+		boolean methodNameSet = false;
+		
+		int lineNum = -1;
+		String line;
+		while((line = r.readLine()) != null) {
+			lineNum++;
+			
+			methodNameSet = false;
+			
+			matcher = SCOPE_PATTERN.matcher(line);
+			if(matcher.matches()) {
+				String name = matcher.group(1);
+				currentScope = new Scope(name, currentMethod);
+				currentMethod.add(currentScope);
+			}
+            
+            matcher = METHOD_PATTERN.matcher(line);
+            boolean methodPatternMatches = matcher.matches();
+            
+            if(methodPatternMatches){
+                currentScope = null;
+				String name = matcher.group(1);
+				boolean isStub = Boolean.parseBoolean(matcher.group(2));
+				currentMethod.init(name, isStub);
+				model.add(currentMethod);
+				methodNameSet = true;
+            }
+			
+			Node currentNode = null;
+			matcher = NODE_PATTERN.matcher(line);
+			if(matcher.matches()) {
+                if(currentScope == null){
+                	raiseError(lineNum, line, "scope is missing");
+                	continue;
+                }
+				int number = Integer.parseInt(matcher.group(1));
+				currentNode = currentScope.getNode(number);
+				if(currentNode == null) {
+					String name = matcher.group(2);
+					currentNode = new Node(number, name, currentScope);
+					currentScope.add(currentNode);
+				}
+			}
+			
+			FileLine fileLine = seekableFile.get(lineNum);
+			LogLine log = new LogLine(lineNum, fileLine, currentMethod, currentScope, currentNode);
+			if(currentNode != null) currentNode.add(log);
+			if(currentScope != null) currentScope.add(log);
+			currentMethod.add(log);
+			model.add(log);
+            
+            if(methodPatternMatches) {
+				currentMethod = new Method(model);
+			}
+		}
+		
+		if(!methodNameSet) raiseError(lineNum, line, "unexpected end of stream");
+		
+		return model;
+	}
+	
+	private void raiseError(int lineNum, String line, String message) {
+		ParseError error = new ParseError(lineNum, line, message);
+		errors.add(error);
+		for(ParseErrorListener listener : errorListeners) {
+			listener.errorOccurred(error);
+		}
+	}
+	
+	/**
+	 * Adds a ParseErrorListener to the listeners
+	 * @param listener
+	 */
+	public void addParseErrorListener(ParseErrorListener listener) {
+		errorListeners.add(listener);
+	}
+	
+	public void removeParseErrorListener(ParseErrorListener listener) {
+		errorListeners.remove(listener);
+	}
+	
+	/**
+	 * Checks if errors occurred during the parsing process
+	 * @return <code>true</code> if there are errors stored, <code>false</code> otherwise
+	 */
+	public boolean hasErrors() {
+		return !errors.isEmpty();
+	}
+	
+	/**
+	 * Returns a list of all errors.
+	 * @return error list
+	 */
+	public List<ParseError> getErrors() {
+		return Collections.unmodifiableList(errors);
+	}
+	
+	public static class ParseError {
+		
+		private final int lineNum;
+		private final String line;
+		private final String message;
+		
+		private ParseError(int lineNum, String line, String message) {
+			this.lineNum = lineNum;
+			this.message = message;
+			this.line = line;
+		}
+		
+		public int getLineNumber() {
+			return lineNum;
+		}
+		
+		public String getLine() {
+			return line;
+		}
+		
+		public String getMessage() {
+			return message;
+		}
+		
+	}
+	
+	public static interface ParseErrorListener {
+		
+		/**
+		 * Called when a new error occurs.<br><br>
+		 * <b>Attention</b>: This method runs on the same thread as the parsing process.
+		 * If time-consuming tasks should be executed, please consider multithreading.
+		 * @param error
+		 */
+		public void errorOccurred(ParseError error);
+		
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Method.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,106 @@
+/*
+ * 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.logviewer.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class Method {
+
+	private String name;
+	private boolean isStub;
+	private final LogModel model;
+	private List<Scope> scopes = new ArrayList<>();
+	private List<LogLine> logs = new ArrayList<>();
+	
+	Method(LogModel model) {
+		name = null;
+		isStub = false;
+		this.model = model;
+	}
+	
+	void init(String name, boolean isStub) {
+		this.name = name;
+		this.isStub = isStub;
+	}
+	
+	/**
+	 * Returns the name of the method
+	 * @return the method name
+	 */
+	public String getName() {
+		return name;
+	}
+	
+	/**
+	 * Returns <code>true</code> if this is a stub method.
+	 * @return <code>true</code> if is stub, <code>false</code> otherwise
+	 */
+	public boolean isStub() {
+		return isStub;
+	}
+	
+	/**
+	 * Returns the model which holds this method.
+	 * @return model-object
+	 */
+	public LogModel getModel() {
+		return model;
+	}
+	
+	void add(Scope scope) {
+		scopes.add(scope);
+	}
+	
+	/**
+	 * Returns a list of all scopes inside a target method.
+	 * @return list of scopes
+	 */
+	public List<Scope> getScopes() {
+		return scopes;
+	}
+	
+	void add(LogLine log) {
+		logs.add(log);
+	}
+	
+	/**
+	 * Returns a list of all logs in the context of the method.
+	 * @return list of log lines
+	 */
+	public List<LogLine> getLogs() {
+		return Collections.unmodifiableList(logs);
+	}
+	
+	/**
+	 * The string representation of a method is its name.
+	 */
+	@Override
+	public String toString() {
+		return getName();
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Node.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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.logviewer.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class Node {
+
+	private final int number;
+	private final String name;
+	private final Scope scope;
+	private List<LogLine> logs = new ArrayList<>();
+	
+	
+	Node(int number, String name, Scope scope) {
+		this.number = number;
+		this.name = name;
+		this.scope = scope;
+	}
+	
+	/**
+	 * Returns the node number.
+	 * @return the node number
+	 */
+	public int getNumber() {
+		return number;
+	}
+	
+	/**
+	 * Returns the node name.
+	 * @return the node name
+	 */
+	public String getName() {
+		return name;
+	}
+	
+	/**
+	 * Returns the parent scope.
+	 * @return the parent scope
+	 */
+	public Scope getScope() {
+		return scope;
+	}
+	
+	void add(LogLine log) {
+		logs.add(log);
+	}
+	
+	/**
+	 * Returns a list of all logs within a nodes context.
+	 * @return list of log lines
+	 */
+	public List<LogLine> getLogs() {
+		return Collections.unmodifiableList(logs);
+	}
+	
+	/**
+	 * The string represenation of a node is &quot;&lt;name&gt; (&lt;number&gt;)&quot;.
+	 */
+	@Override
+	public String toString() {
+		return getName() + "(" + getNumber() + ")";
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Scope.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,104 @@
+/*
+ * 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.logviewer.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class Scope {
+
+	private final String name;
+	private final Method method;
+	private List<Node> nodes = new ArrayList<>();
+	private List<LogLine> logs = new ArrayList<>();
+	
+	Scope(String name, Method method) {
+		this.name = name;
+		this.method = method;
+	}
+	
+	/**
+	 * Returns the scope name.
+	 * @return the scope name
+	 */
+	public String getName() {
+		return name;
+	}
+	
+	/**
+	 * Returns the parent method.
+	 * @return the parent method
+	 */
+	public Method getMethod() {
+		return method;
+	}
+	
+	void add(Node node) {
+		nodes.add(node);
+	}
+	
+	/**
+	 * Returns a list of all node-objects inside a scope.
+	 * @return list of nodes
+	 */
+	public List<Node> getNodes() {
+		return Collections.unmodifiableList(nodes);
+	}
+	
+	void add(LogLine log) {
+		logs.add(log);
+	}
+	
+	/**
+	 * Returns a list of all logs inside a scope.
+	 * @return list of log lines
+	 */
+	public List<LogLine> getLogs() {
+		return logs;
+	}
+	
+	/**
+	 * Returns the node inside a scope with the given number.
+	 * @param number node number
+	 * @return node-object
+	 */
+	public Node getNode(int number) {
+		for(Node node : nodes) {
+			if(node.getNumber() == number) return node;
+		}
+		return null;
+	}
+	
+	/**
+	 * The string representation of a scope is its name.
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		return getName();
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/Filter.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.logviewer.model.filter;
+
+import com.oracle.graal.visualizer.logviewer.model.LogLine;
+
+public interface Filter {
+
+	/**
+	 * Sets the constraints for a filter.<br>
+	 * They can be every type of objects. In general these are strings, but it can also be
+	 * a Integer (like in the <code>NodeFilter</code>):<br>
+	 * <code>Filter nodeFilter = filterManager.getNodeFilter();
+	 * filter.setConstraints((String)nodeName, (Integer)nodeNumber);</code>
+	 * @param constraints filter constraints
+	 */
+	void setConstraints(Object ... constraints);
+	
+	/**
+	 * Indicates whether to keep a log line in the filter results, or not.
+	 * @param line log line which should be checked
+	 * @return <code>true</code> if the line should be kept, <code>false</code> otherwise
+	 */
+	boolean keep(LogLine line);
+	
+	/**
+	 * Activates or deactivates a filter. Deactivated filters will be ignored.
+	 * @param active <code>true</code> to activate, <code>false</code> to deactivate
+	 */
+	void setActive(boolean active);
+	
+	/**
+	 * Returns the activation status
+	 * @return <code>true</code> for an active filter, <code>false</code> otherwise
+	 */
+	boolean isActive();
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/FilterManager.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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.logviewer.model.filter;
+
+import com.oracle.graal.visualizer.logviewer.model.LogLine;
+import com.oracle.graal.visualizer.logviewer.model.LogModel;
+import java.util.ArrayList;
+import java.util.List;
+
+public class FilterManager {
+	
+	private final List<Filter> filters = new ArrayList<>();
+	private final Filter methodFilter, scopeFilter, nodeFilter, fulltextFilter;
+	
+	/**
+	 * Creates a new instance of the filter manager.
+	 */
+	public FilterManager() {
+		add(methodFilter = new MethodFilter());
+		add(scopeFilter = new ScopeFilter());
+		add(nodeFilter = new NodeFilter());
+		add(fulltextFilter = new FullTextFilter());
+	}
+	
+	/**
+	 * Executes a filtering process with the given log model as subject. Inactive filters will be ignored.
+	 * @param model subject
+	 * @return filtered list of log lines
+	 * @throws InterruptedException 
+	 */
+	public List<LogLine> execute(LogModel model) throws InterruptedException {
+		List<LogLine> input = model.getLogs();
+		List<LogLine> output = new ArrayList<>();
+		
+		for(LogLine line : input) {
+			if(Thread.interrupted()) throw new InterruptedException();
+			if(keep(line)) output.add(line);
+		}
+		
+		if(Thread.interrupted()) throw new InterruptedException();
+		
+		return output;
+	}
+	
+	private boolean keep(LogLine line) {
+		boolean keep = true;
+		for(Filter filter : filters) {
+			keep = keep && (!filter.isActive() || filter.keep(line));
+		}
+		return keep;
+	}
+	
+	private Filter add(Filter filter) {
+		filters.add(filter);
+		return filter;
+	}
+	
+	/**
+	 * Returns the instance of a method filter
+	 * @return method filter
+	 */
+	public Filter getMethodFilter() {
+		return methodFilter;
+	}
+	
+	/**
+	 * Returns the instance of a scope filter
+	 * @return scope filter
+	 */
+	public Filter getScopeFilter() {
+		return scopeFilter;
+	}
+	
+	/**
+	 * Returns the instance of a node filter
+	 * @return node filter
+	 */
+	public Filter getNodeFilter() {
+		return nodeFilter;
+	}
+	
+	/**
+	 * Returns the instance of a full text filter
+	 * @return full text filter
+	 */
+	public Filter getFullTextFilter() {
+		return fulltextFilter;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/FullTextFilter.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,73 @@
+/*
+ * 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.logviewer.model.filter;
+
+import com.oracle.graal.visualizer.logviewer.model.LogLine;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+class FullTextFilter implements Filter {
+
+	private Pattern p;
+	private boolean active = true;
+	
+	@Override
+	public void setConstraints(Object ... constraints) {
+        this.p = null;
+		for(Object constraint : constraints) {
+			setConstraint(constraint);
+		}
+	}
+	
+	private void setConstraint(Object constraint) {
+		if(constraint instanceof String) {
+			if(((String)constraint).trim().length() > 0) {
+				this.p = Pattern.compile((String)constraint);
+			}
+			else {
+				this.p = null;
+			}
+		}
+	}
+
+	@Override
+	public boolean keep(LogLine line) {
+		if(p == null) return true;
+		
+		Matcher matcher = p.matcher(line.getText());
+		return matcher.find();
+	}
+
+	@Override
+	public void setActive(boolean active) {
+		this.active = active;
+	}
+
+	@Override
+	public boolean isActive() {
+		return active;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/MethodFilter.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,73 @@
+/*
+ * 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.logviewer.model.filter;
+
+import com.oracle.graal.visualizer.logviewer.model.LogLine;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+class MethodFilter implements Filter {
+
+	private Pattern p;
+	private boolean active = true;
+	
+	@Override
+	public void setConstraints(Object ... constraints) {
+        this.p = null;
+		for(Object constraint : constraints) {
+			setConstraint(constraint);
+		}
+	}
+	
+	private void setConstraint(Object constraint) {
+		if(constraint instanceof String) {
+			if(((String)constraint).trim().length() > 0) {
+				this.p = Pattern.compile((String)constraint);
+			}
+			else {
+				this.p = null;
+			}
+		}
+	}
+
+	@Override
+	public boolean keep(LogLine line) {
+		if(p == null) return true;
+		
+		Matcher matcher = p.matcher(line.getMethod().getName());
+		return matcher.find();
+	}
+
+	@Override
+	public void setActive(boolean active) {
+		this.active = active;
+	}
+
+	@Override
+	public boolean isActive() {
+		return active;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/NodeFilter.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,91 @@
+/*
+ * 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.logviewer.model.filter;
+
+import com.oracle.graal.visualizer.logviewer.model.LogLine;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+class NodeFilter implements Filter {
+
+	private Pattern p;
+	private Integer nodeNum;
+	private boolean active = true;
+	
+	@Override
+	public void setConstraints(Object ... constraints) {
+        this.nodeNum = null;
+        this.p = null;
+		for(Object constraint : constraints) {
+			setConstraint(constraint);
+		}
+	}
+	
+	private void setConstraint(Object constraint) {
+		if(constraint instanceof String) {
+		
+			if(((String)constraint).trim().length() > 0) {
+				this.p = Pattern.compile((String)constraint);
+			}
+			else {
+				this.p = null;
+			}
+		}
+		else if(constraint instanceof Integer) {
+			this.nodeNum = (Integer)constraint;
+		}
+		
+	}
+
+	@Override
+	public boolean keep(LogLine line) {
+		if(p == null && nodeNum == null) return true; 
+		
+		if(line.getNode() == null) return false;
+		
+		boolean keep = false;
+		
+		if(p != null) {
+			Matcher matcher = p.matcher(line.getNode().getName());
+			keep = keep || matcher.find();
+		}
+		if(nodeNum != null) {
+			keep = keep || nodeNum.equals(line.getNode().getNumber());
+		}
+		
+		return keep;		
+	}
+
+	@Override
+	public void setActive(boolean active) {
+		this.active = active;
+	}
+
+	@Override
+	public boolean isActive() {
+		return active;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/ScopeFilter.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.logviewer.model.filter;
+
+import com.oracle.graal.visualizer.logviewer.model.LogLine;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+class ScopeFilter implements Filter {
+
+	private Pattern p;
+	private boolean active = true;
+	
+	@Override
+	public void setConstraints(Object ... constraints) {
+        this.p = null;
+		for(Object constraint : constraints) {
+			setConstraint(constraint);
+		}
+	}
+	
+	private void setConstraint(Object constraint) {
+		if(constraint instanceof String) {
+			if(((String)constraint).trim().length() > 0) {
+				this.p = Pattern.compile((String)constraint);
+			}
+			else {
+				this.p = null;
+			}
+		}
+	}
+
+	@Override
+	public boolean keep(LogLine line) {
+		if(p == null) return true;
+        
+        if(line.getScope() == null) return false;
+		
+		Matcher matcher = p.matcher(line.getScope().getName());
+		return matcher.find();
+	}
+
+	@Override
+	public void setActive(boolean active) {
+		this.active = active;
+	}
+
+	@Override
+	public boolean isActive() {
+		return active;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/FileLine.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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.logviewer.model.io;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+
+public class FileLine implements CharSequence {
+
+	private final SeekableFile seekableFile;
+	private WeakReference<String> cache;
+	public final long off;
+	public final int len;
+	
+	public FileLine(SeekableFile seekableFile, long off, int len) {
+		this.seekableFile = seekableFile;
+		this.off = off;
+		this.len = len;
+	}
+	
+	@Override
+	public String toString() {
+		String line = null;
+		
+		if(cache != null) line = cache.get();
+		
+		if(line == null) {
+			try {
+				line = seekableFile.read(this);
+				cache = new WeakReference<>(line);
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+		
+		return line;
+	}
+
+	@Override
+	public int length() {
+		return len;
+	}
+
+	@Override
+	public char charAt(int index) {
+		String line = toString();
+		return line != null ? line.charAt(index) : 0;
+	}
+
+	@Override
+	public CharSequence subSequence(int start, int end) {
+		String line = toString();
+		return line != null ? line.subSequence(start, end) : "";
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/ProgressMonitor.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.logviewer.model.io;
+
+public interface ProgressMonitor {
+
+	/**
+	 * Triggered when some work has been done.<br><br>
+	 * <b>Attention</b>: This method runs on the same thread as the reading process.
+	 * If time-consuming tasks should be executed, please consider multithreading.
+	 * @param percentage Value in range between 0 and 1 to indicate how much work has been done.
+	 */
+	public void worked(float percentage);
+	
+	/**
+	 * Triggered when work is done completely.<br><br>
+	 * <b>Attention</b>: This method runs on the same thread as the reading process.
+	 * If time-consuming tasks should be executed, please consider multithreading.
+	 */
+	public void finished();
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/SeekableFile.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,70 @@
+/*
+ * 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.logviewer.model.io;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SeekableFile implements Closeable {
+
+	private final RandomAccessFile raf;
+	private List<FileLine> lines = new ArrayList<>();
+	
+	SeekableFile(File file) throws FileNotFoundException {
+		raf = new RandomAccessFile(file, "r");
+	}
+	
+	void addLine(long off, int len) {
+		lines.add(new FileLine(this, off, len));
+	}
+	
+	public int size() {
+		return lines.size();
+	}
+	
+	public FileLine get(int lineNum) throws IOException {
+		FileLine line = lines.get(lineNum);
+		return line;
+	}
+	
+	String read(FileLine line) throws IOException {
+		if(line == null) throw new IllegalArgumentException("line is null");
+		raf.seek(line.off);
+
+		byte [] buf = new byte[line.len];
+		
+		if(raf.read(buf) != line.len) throw new IOException("error while reading line");
+		
+		return new String(buf);
+	}
+
+	@Override
+	public void close() throws IOException {
+		raf.close();
+	}
+	
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/SeekableFileReader.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,121 @@
+/*
+ * 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.logviewer.model.io;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+
+public class SeekableFileReader extends Reader {
+	
+	public static final int DEFAULT_GAP = 1024; // in bytes
+
+	private final FileReader reader;
+	private SeekableFile seekableFile;
+	private ProgressMonitor monitor;
+	private long filelen;
+	private int gap;
+	
+	public SeekableFileReader(File file) throws IOException {
+		super(file);
+		reader = new FileReader(file);
+		seekableFile = new SeekableFile(file);
+	}
+	
+	public SeekableFileReader(File file, ProgressMonitor monitor, int gap) throws IOException {
+		this(file);
+		this.monitor = monitor;
+		this.filelen = file.length();
+		this.gap = gap;
+	}
+	
+	public SeekableFileReader(File file, ProgressMonitor monitor) throws IOException {
+		this(file, monitor, DEFAULT_GAP);
+	}
+	
+	public SeekableFile getSeekableFile() {
+		return seekableFile;
+	}
+
+    @Override
+	public void close() throws IOException {
+		reader.close();		
+	}
+	
+	private long bytes = 0;
+	private boolean skipLF = false;
+	private long off;
+	private long lastGapped = 0;
+	private boolean finished = false;
+
+	@Override
+	public int read(char[] cbuf, int offset, int length) throws IOException {
+		
+		int l = reader.read(cbuf, offset, length);
+		
+		if(l == -1 && !finished) {
+			seekableFile.addLine(off, (int)(bytes-off));
+			finished = true;
+			if(monitor != null) {
+				monitor.worked(1);
+				monitor.finished();
+			}
+		}
+		
+		for(int i = 0; i < l; ++i) {
+			Character ch = new Character(cbuf[i]);
+			int chlen = ch.toString().getBytes(reader.getEncoding()).length;
+				
+			if(skipLF && ch != '\n') {
+				seekableFile.addLine(off, (int)(bytes-off-chlen));
+				off = bytes;
+				skipLF = false;
+			}
+			
+			bytes += chlen;
+			
+			if(monitor != null) {
+				if(bytes > lastGapped+gap) {
+					lastGapped = bytes;
+					monitor.worked(((float)bytes)/((float)filelen));
+				}
+			}
+			
+			if(ch == '\r') {
+				skipLF = true;
+			}
+			if(ch == '\n') {
+				seekableFile.addLine(off, (int)(bytes-off-(skipLF ? 2*chlen : chlen)));
+				off = bytes;
+				skipLF = false;
+			}
+		}
+		
+		return l;
+	}
+	
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/BookmarkDialog.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,114 @@
+/*
+ * 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.logviewer.scene;
+
+import com.oracle.graal.visualizer.logviewer.model.LogLine;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.List;
+import javax.swing.*;
+
+public class BookmarkDialog extends JDialog {
+    
+    private JList lstBookmarks;
+    private List<LogLine> logLines;
+    
+    public BookmarkDialog(List<LogLine> bookmarks, Window parent) {
+        super(parent, JDialog.ModalityType.APPLICATION_MODAL);
+        
+        this.logLines = bookmarks;
+        
+        DefaultListModel mdlBookmarks = new DefaultListModel();
+        lstBookmarks = new JList(mdlBookmarks);
+        JScrollPane jspBookmarks = new JScrollPane(lstBookmarks);
+        
+        for (LogLine bookmark : bookmarks) {
+            mdlBookmarks.addElement(bookmark.getLineNumber() + ": Method " + bookmark.getMethod() + " - Scope " + bookmark.getScope() + " - " + bookmark.getText());
+        }
+        
+        JButton btnOk = new JButton("Go to");
+        JButton btnCancel = new JButton("Cancel");
+
+        // init listeners
+        lstBookmarks.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mouseClicked(MouseEvent e) {
+                if (e.getClickCount() == 2) {
+                    close();
+                }
+            }
+        });
+        
+        btnOk.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent ae) {
+                if (lstBookmarks.isSelectionEmpty())
+                    return;
+                close();
+            }
+        });
+        btnCancel.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent ae) {
+                lstBookmarks.clearSelection();
+                close();
+            }
+        });
+        
+        // build layout
+        JPanel pnlButtons = new JPanel();
+        
+        pnlButtons.setLayout(new GridLayout(1, 2));
+        pnlButtons.add(btnOk);
+        pnlButtons.add(btnCancel);
+        
+        this.setLayout(new BorderLayout());
+        this.add(jspBookmarks, BorderLayout.CENTER);
+        this.add(pnlButtons, BorderLayout.SOUTH);
+        
+        this.pack();
+        this.setMinimumSize(new Dimension(600, this.getPreferredSize().height));
+        this.setLocationRelativeTo(parent);
+        this.setResizable(false);
+        this.setVisible(true);
+    }
+    
+    public LogLine getTarget() {
+        if (lstBookmarks.isSelectionEmpty())
+            return null;
+        return logLines.get(lstBookmarks.getSelectedIndex());
+    }
+    
+    private void close() {
+        this.setVisible(false);
+        this.dispose();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/BookmarkableLogViewer.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,378 @@
+/*
+ * 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.logviewer.scene;
+
+import com.oracle.graal.visualizer.logviewer.model.LogLine;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DefaultHighlighter;
+import javax.swing.text.Highlighter;
+import javax.swing.text.JTextComponent;
+import org.openide.util.Exceptions;
+
+public class BookmarkableLogViewer extends JPanel {
+
+    private static final Color BOOKMARK_COLOR = Color.CYAN;
+    
+    private static final Highlighter.HighlightPainter BOOKMARK_PAINTER =
+            new DefaultHighlighter.DefaultHighlightPainter(BOOKMARK_COLOR);
+    
+    private JTextPane txpText;
+    private JTextPane txpLines;
+    private Highlighter textHighlighter;
+    private Highlighter lineHighlighter;
+    private FontMetrics fm;
+    private Map<Integer, Bookmark> bookmarks = new TreeMap<>();
+    private List<LogLine> logLines = new ArrayList<>();
+
+    public BookmarkableLogViewer() {
+        init();
+    }
+
+    private void init() {
+        txpText = new JTextPane();
+        txpLines = new JTextPane();
+
+        // needed for correct layouting
+        Insets ins = txpLines.getInsets();
+        txpLines.setMargin(new Insets(ins.top + 1, ins.left, ins.bottom, ins.right));
+
+        textHighlighter = new BookmarkHighlighter();
+        lineHighlighter = new BookmarkHighlighter();
+
+        txpText.setHighlighter(textHighlighter);
+        //txpText.setMinimumSize(new Dimension(100, 100));
+        txpText.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
+        txpText.setEditable(false);
+
+        txpLines.setHighlighter(lineHighlighter);
+        txpLines.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
+        txpLines.setBackground(Color.LIGHT_GRAY);
+        txpLines.setEnabled(false);
+        txpLines.setForeground(Color.BLACK);
+        txpLines.addMouseListener(mouseInputListener);
+
+        fm = txpText.getFontMetrics(txpText.getFont());
+
+        JPanel pnlBookmarks = new JPanel();
+        pnlBookmarks.setLayout(new BorderLayout());
+        pnlBookmarks.add(txpText, BorderLayout.CENTER);
+
+        JScrollPane jspBookmarks = new JScrollPane(pnlBookmarks);
+        jspBookmarks.setRowHeaderView(txpLines);
+        jspBookmarks.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+        jspBookmarks.getVerticalScrollBar().setUnitIncrement(15);
+
+        this.setLayout(new BorderLayout());
+        this.add(jspBookmarks, BorderLayout.CENTER);
+    }
+   
+    public int getCurrentlyDisplayedTopLine() {
+        Rectangle view = txpText.getVisibleRect();
+        return getAbsoluteLine((int) Math.ceil(view.y/fm.getHeight()));
+    }
+    
+    public int getCurrentTopLine() {
+        return logLines.get(0).getLineNumber();
+    }
+    
+    public int getCurrentBottomLine() {
+        return logLines.get(logLines.size()-1).getLineNumber();
+    }
+
+    public void clearLogLines() {
+        this.logLines = new ArrayList<>();
+        txpText.setText("");
+        txpLines.setText("");
+        clearHighlighter();
+    }
+
+    public void setLogLines(List<LogLine> logLines) {
+        this.logLines = logLines;
+
+        clearHighlighter();
+        clearLineNumbers();
+        String text = "";
+        for (int i = 0; i < logLines.size(); i++) {
+            text += logLines.get(i).getText();
+            if (i < logLines.size() - 1) {
+                text += "\n";
+            }
+        }
+        txpText.setText(text);
+        setLineNumbers();
+   
+        txpText.setCaretPosition(0);
+        txpLines.setCaretPosition(0);
+
+        for (int bookmark : bookmarks.keySet()) {
+            if (bookmark < logLines.get(0).getLineNumber()) {
+                continue;
+            }
+            if (bookmark > logLines.get(logLines.size() - 1).getLineNumber()) {
+                break;
+            }
+
+            int line = getRelativeLine(bookmark);
+
+            addHighlight(logLines.get(line));
+        }
+    }
+
+    public void setLogLines(List<LogLine> logLines, int focus) {
+        setLogLines(logLines);
+        
+        //does not work for some reason - jtextpane jumps to caret position afterwards
+        //moveToBookmark(focus);
+        
+        //workaround - set caret position bevore moving
+        Rectangle visible = txpText.getVisibleRect();
+        int visibleLines = (int)(Math.ceil(visible.height/fm.getHeight()));
+
+        String text = txpText.getText();
+        int line = logLines.get(0).getLineNumber();
+        for (int i = 0; i < text.length(); i++) {
+            if (text.charAt(i) == '\n')
+                line++;
+            if (line == focus+visibleLines || i == text.length() - 1) {
+                txpText.setCaretPosition(i);
+                break;
+            }
+        }
+        moveToBookmark(focus);
+    }
+
+    public List<LogLine> getBookmarkedLines() {
+        List<LogLine> lines = new ArrayList<>();
+        for (int bookmark : bookmarks.keySet()) {
+            lines.add(bookmarks.get(bookmark).logLine);
+        }
+        return lines;
+    }
+
+    public int tryLastBookmark() {
+        int line = getCurrentlyDisplayedTopLine();
+        
+        int firstShownLine = getCurrentTopLine();
+
+        int bookmarkKey = -1;
+        for (int key : bookmarks.keySet()) {
+            if (key >= line) {
+                break;
+            }
+
+            bookmarkKey = key;
+        }
+
+        if (bookmarkKey >= firstShownLine) {
+            moveToBookmark(bookmarkKey);
+            return -1;
+        }
+
+        return bookmarkKey;
+    }
+
+    public int tryNextBookmark() {
+        Rectangle visible = txpText.getVisibleRect();
+        int lastLine = (int) Math.floor((visible.y + visible.height) / fm.getHeight());
+        lastLine = getAbsoluteLine(lastLine);
+
+        int lastShownLine = getCurrentBottomLine();
+
+        int bookmarkKey = -1;
+        for (int key : bookmarks.keySet()) {
+            if (key > lastLine) {
+                bookmarkKey = key;
+                break;
+            }
+            if (key > lastShownLine) {
+                break;
+            }
+        }
+
+        if (bookmarkKey > 0 && bookmarkKey <= lastShownLine) {
+            moveToBookmark(bookmarkKey);
+            return -1;
+        }
+
+        return bookmarkKey;
+    }
+
+    private void moveToBookmark(int line) {
+        int relLine = getRelativeLine(line);
+        Rectangle visible = txpText.getVisibleRect();
+        Rectangle position = new Rectangle(0, relLine * fm.getHeight(), visible.width, visible.height);
+        txpText.scrollRectToVisible(position);
+    }
+
+    private int getAbsoluteLine(int line) {
+        return logLines.get(0).getLineNumber() + line;
+    }
+
+    private int getRelativeLine(int line) {
+        return line - logLines.get(0).getLineNumber();
+    }
+
+    private int getStartOffset(JTextComponent component, int line) {
+        return component.getDocument().getDefaultRootElement().getElement(line).getStartOffset();
+    }
+
+    private int getEndOffset(JTextComponent component, int line) {
+        return component.getDocument().getDefaultRootElement().getElement(line).getEndOffset();
+    }
+
+    private void addHighlight(LogLine logLine) {
+        try {
+            int line = logLine.getLineNumber();
+            int relativeLine = getRelativeLine(line);
+
+            Object hl1 = textHighlighter.addHighlight(getStartOffset(txpText, relativeLine), getEndOffset(txpText, relativeLine), BOOKMARK_PAINTER);
+            Object hl2 = lineHighlighter.addHighlight(getStartOffset(txpLines, relativeLine), getEndOffset(txpLines, relativeLine), BOOKMARK_PAINTER);
+            bookmarks.put(line, new Bookmark(logLine, hl1, hl2));
+        } catch (BadLocationException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+    }
+
+    private void removeHighlight(int line) {
+        int abs = getAbsoluteLine(line);
+        Bookmark bookmark = bookmarks.get(abs);
+        textHighlighter.removeHighlight(bookmark.hl1);
+        lineHighlighter.removeHighlight(bookmark.hl2);
+        bookmarks.remove(abs);
+    }
+
+    public void clearBookmarks() {
+        bookmarks = new TreeMap<>();
+        clearHighlighter();
+    }
+
+    private void clearHighlighter() {
+        textHighlighter.removeAllHighlights();
+        lineHighlighter.removeAllHighlights();
+    }
+
+    private void clearLineNumbers() {
+        txpLines.setText("");
+    }
+
+    private void setLineNumbers() {
+        clearLineNumbers();
+
+        if (logLines.isEmpty()) {
+            return;
+        }
+
+        int colCnt = String.valueOf(logLines.get(logLines.size() - 1).getLineNumber()).length() + 2;
+
+        int firstNr = logLines.get(0).getLineNumber();
+        String text = String.format("%" + colCnt + "s", firstNr + " ");
+        for (int i = 1; i < logLines.size(); i++) {
+            text += "\n";
+            text += String.format("%" + colCnt + "s", (firstNr + i) + " ");
+        }
+        txpLines.setText(text);
+    }
+
+    private MouseListener mouseInputListener = new MouseAdapter() {
+
+        @Override
+        public void mouseClicked(MouseEvent me) {
+            if (txpLines.getText().length() == 0) {
+                return;
+            }
+            if (me.getClickCount() == 2) {
+                int caretPos = txpLines.getCaretPosition();
+
+                int lineOffset = txpLines.getDocument().getDefaultRootElement().getElementIndex(caretPos);
+                if (txpLines.getText().charAt(caretPos - 1) == '\n') {
+                    lineOffset--;
+                }
+
+                if (bookmarks.containsKey(getAbsoluteLine(lineOffset))) {
+                    removeHighlight(lineOffset);
+                } else {
+                    addHighlight(logLines.get(lineOffset));
+                }
+            }
+        }
+    };
+
+    class Bookmark {
+
+        public final LogLine logLine;
+        public final Object hl1;
+        public final Object hl2;
+
+        public Bookmark(LogLine logLine, Object hl1, Object hl2) {
+            this.logLine = logLine;
+            this.hl1 = hl1;
+            this.hl2 = hl2;
+        }
+    }
+
+    class BookmarkHighlighter extends DefaultHighlighter {
+
+        private JTextComponent component;
+
+        @Override
+        public void install(JTextComponent component) {
+            super.install(component);
+            this.component = component;
+        }
+
+        @Override
+        public void deinstall(JTextComponent component) {
+            super.deinstall(component);
+            this.component = null;
+        }
+
+        @Override
+        public void paint(Graphics g) {
+            Highlighter.Highlight[] highlights = getHighlights();
+
+            for (int i = 0; i < highlights.length; i++) {
+                Highlighter.Highlight hl = highlights[i];
+                Rectangle bg = component.getBounds();
+                Insets insets = component.getInsets();
+                bg.x = insets.left;
+                bg.y = insets.top;
+                bg.height = insets.top + insets.bottom;
+                Highlighter.HighlightPainter painter = hl.getPainter();
+                painter.paint(g, hl.getStartOffset(), hl.getEndOffset(), bg, component);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/ImportLogErrorDialog.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,51 @@
+/*
+ * 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.logviewer.scene;
+
+import com.oracle.graal.visualizer.logviewer.model.LogParser;
+import java.awt.Component;
+import java.util.List;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+public class ImportLogErrorDialog {
+    
+    public static void showDialog(Component parent, List<LogParser.ParseError> errors) {
+        JTextArea txaErrors = new JTextArea();
+        
+        for (LogParser.ParseError error : errors) {
+            txaErrors.append("Error at line " + error.getLineNumber());
+            txaErrors.append(": " + error.getMessage());
+            txaErrors.append("\n");
+            txaErrors.append("Log line: " + error.getLine());
+            txaErrors.append("\n");
+        }
+        
+        JScrollPane scpErrors = new JScrollPane(txaErrors);
+        
+        JOptionPane.showMessageDialog(parent, scpErrors, "Parse errors", JOptionPane.ERROR_MESSAGE);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/LogScene.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,671 @@
+/*
+ * 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.logviewer.scene;
+
+import com.oracle.graal.visualizer.logviewer.model.LogLine;
+import com.oracle.graal.visualizer.logviewer.model.LogModel;
+import com.oracle.graal.visualizer.logviewer.model.LogParser;
+import com.oracle.graal.visualizer.logviewer.model.filter.Filter;
+import com.oracle.graal.visualizer.logviewer.model.filter.FilterManager;
+import com.oracle.graal.visualizer.logviewer.model.io.ProgressMonitor;
+import com.oracle.graal.visualizer.logviewer.scene.model.LogTableModel;
+import com.oracle.graal.visualizer.logviewer.scene.model.TableLine;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.regex.PatternSyntaxException;
+import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableColumn;
+import org.openide.util.Exceptions;
+import org.openide.util.NbPreferences;
+import sun.awt.CausedFocusEvent;
+
+public class LogScene extends JPanel {
+    private static final String PREFERENCE_DIR = "dir";
+    
+    private static final String ICON_PREFIX = "/com/oracle/graal/visualizer/logviewer/scene/icons/";
+    private static final String ICON_ARROW_DOWN = ICON_PREFIX + "arrow_down.png";
+    private static final String ICON_ARROW_UP = ICON_PREFIX + "arrow_up.png";
+    private static final String ICON_BOOKMARK_BACK = ICON_PREFIX + "bookmark_back.png";
+    private static final String ICON_BOOKMARK_FWD = ICON_PREFIX + "bookmark_forward.png";
+    private static final String ICON_BOOKMARK_LIST = ICON_PREFIX + "bookmark_list.png";
+    private static final String ICON_LOAD = ICON_PREFIX + "loading.gif";
+    
+    private static final ImageIcon IMGICON_LOAD = new ImageIcon(LogScene.class.getResource(ICON_LOAD));
+    
+    private static final int LOG_LINES = 50;
+    private static final int KEYSTROKE_RATE = 100; // rate at which the keystrokes are checked
+    private static final int KEYSTROKE_TRESHOLD = 400; // time in ms after which a search is triggered
+            
+    private FilterManager filterManager;
+    private Thread filterRunThread;
+    
+    private int timeSinceLastKeystroke = -1;
+    
+    private JLabel lblMessage;
+    private JLabel lblIcon;
+    
+    private JLabel lblMethodFilter;
+    private JLabel lblScopeFilter;
+    private JLabel lblNodeFilter;
+    private JLabel lblFulltextFilter;
+    private JTextField txfMethodFilter;
+    private JTextField txfScopeFilter;
+    private JTextField txfNodeFilter;
+    private JTextField txfFulltextFilter;
+    
+    private JTable tblResult;
+    private LogTableModel tblResultModel;
+    
+    private BookmarkableLogViewer logViewer;
+    private JButton btnBookmarkBack;
+    private JButton btnBookmarkFwd;
+    private JButton btnBookmarkList;
+    private JButton btnLoadMoreUp;
+    private JButton btnLoadMoreDown;
+    
+    private LogParser parser = new LogParser();
+    private LogModel logModel = null;
+    private LogStatus logStatus = LogStatus.NO_LOG;
+    
+    private static LogScene instance;
+    
+    private enum LogStatus {
+        NO_LOG, LOADING, ACTIVE
+    }
+
+    public static LogScene getInstance() {
+        return instance;
+    }
+    
+    public LogScene() {
+        initComponents();
+    }
+    
+    private void initComponents() {
+        filterManager = new FilterManager();
+        
+        lblMessage = new JLabel("No logfile loaded.");
+        lblIcon = new JLabel("");
+        
+        // Initialize filter components
+        lblMethodFilter = new JLabel("Target Method:");
+        lblScopeFilter = new JLabel("Scope:");
+        lblNodeFilter = new JLabel("Node:");
+        lblFulltextFilter = new JLabel("Fulltext:");
+        
+        txfMethodFilter = new JTextField();
+        txfScopeFilter = new JTextField();
+        txfNodeFilter = new JTextField();
+        txfFulltextFilter = new JTextField();
+        
+        tblResultModel = new LogTableModel();
+        tblResult = new JTable(tblResultModel);
+        tblResult.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        tblResult.getTableHeader().setReorderingAllowed(false);
+        tblResult.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
+        
+        Dimension dim = tblResult.getPreferredScrollableViewportSize();
+        tblResult.setPreferredScrollableViewportSize(new Dimension(dim.width, 10*tblResult.getRowHeight() + tblResult.getTableHeader().getHeight()));
+        JScrollPane scpTblResult = new JScrollPane(tblResult);
+        scpTblResult.setMinimumSize(new Dimension(dim.width, 10*tblResult.getRowHeight() + tblResult.getTableHeader().getHeight()));
+        
+        logViewer = new BookmarkableLogViewer();
+        
+        btnLoadMoreUp = new JButton(new ImageIcon(LogScene.class.getResource(ICON_ARROW_UP)));
+        btnLoadMoreDown = new JButton(new ImageIcon(LogScene.class.getResource(ICON_ARROW_DOWN)));
+        
+        btnLoadMoreUp.setFocusable(false);
+        btnLoadMoreUp.setToolTipText("Load more previous log lines");
+        
+        btnLoadMoreDown.setFocusable(false);
+        btnLoadMoreDown.setToolTipText("Load more following log lines");
+        
+        btnBookmarkBack = new JButton(new ImageIcon(LogScene.class.getResource(ICON_BOOKMARK_BACK)));
+        btnBookmarkList = new JButton(new ImageIcon(LogScene.class.getResource(ICON_BOOKMARK_LIST)));
+        btnBookmarkFwd = new JButton(new ImageIcon(LogScene.class.getResource(ICON_BOOKMARK_FWD)));
+        
+        btnBookmarkBack.setFocusable(false);
+        btnBookmarkBack.setToolTipText("Navigate to the last bookmark.");
+        
+        btnBookmarkFwd.setFocusable(false);
+        btnBookmarkFwd.setToolTipText("Navigate to the next bookmark.");
+        
+        btnBookmarkList.setFocusable(false);
+        btnBookmarkList.setToolTipText("List all known bookmarks.");
+        
+        JPanel pnl = new JPanel();
+        pnl.setLayout(new GridBagLayout());
+        pnl.setOpaque(false);
+        
+        JPanel logViewerPanel = new JPanel();
+        logViewerPanel.setLayout(new GridBagLayout());
+        logViewerPanel.setOpaque(false);
+        
+        JPanel messagePanel = new JPanel();
+        messagePanel.setLayout(new BoxLayout(messagePanel, BoxLayout.LINE_AXIS));
+        messagePanel.setOpaque(false);
+        
+        // Initialize Listeners
+        initListeners();
+        
+        // Layout components
+        GridBagConstraints gbc = new GridBagConstraints();
+        
+        messagePanel.add(lblMessage);
+        messagePanel.add(Box.createHorizontalGlue());
+        messagePanel.add(lblIcon);
+        
+        Insets standardInsets = gbc.insets;
+        
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.anchor = GridBagConstraints.WEST;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        gbc.weightx = 1;
+        gbc.weighty = 0;
+        gbc.gridwidth = 2;
+        gbc.insets = new Insets(2, 0, 2, 0);
+        pnl.add(messagePanel, gbc);
+        
+        gbc.fill = GridBagConstraints.NONE;
+        gbc.gridwidth = 1;
+        gbc.weightx = 0;
+        gbc.weighty = 0;
+        gbc.gridy++;
+        gbc.insets = standardInsets;
+        pnl.add(lblMethodFilter, gbc);
+        
+        gbc.gridy++;
+        pnl.add(lblScopeFilter, gbc);
+        
+        gbc.gridy++;
+        pnl.add(lblNodeFilter, gbc);
+        
+        gbc.gridy++;
+        pnl.add(lblFulltextFilter, gbc);
+        
+        gbc.gridx++;
+        gbc.gridy = 1;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        gbc.weightx = 0.75;
+        pnl.add(txfMethodFilter, gbc);
+        
+        gbc.gridy++;
+        pnl.add(txfScopeFilter, gbc);
+        
+        gbc.gridy++;
+        pnl.add(txfNodeFilter, gbc);
+        
+        gbc.gridy++;
+        pnl.add(txfFulltextFilter, gbc);
+        
+        gbc.gridx = 0;
+        //gbc.gridy++;
+        gbc.gridwidth = 2;
+        gbc.weightx = 1;
+        gbc.anchor = GridBagConstraints.FIRST_LINE_START;
+        //pnl.add(btnSearch, gbc);
+        
+        gbc.gridy++;
+        pnl.add(scpTblResult, gbc);
+        
+        gbc.gridy++;
+        gbc.weighty = 1;
+        gbc.fill = GridBagConstraints.BOTH;
+        pnl.add(logViewerPanel, gbc);
+        
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.gridheight = 6;
+        gbc.weightx = 1;
+        gbc.weighty = 1;
+        gbc.fill = GridBagConstraints.BOTH;
+        logViewerPanel.add(logViewer, gbc);
+        
+        gbc.gridx++;
+        gbc.weightx = 0;
+        gbc.weighty = 0;
+        gbc.fill = GridBagConstraints.NONE;
+        gbc.anchor = GridBagConstraints.PAGE_START;
+        gbc.gridheight = 1;
+        logViewerPanel.add(btnLoadMoreUp, gbc);
+        
+        gbc.gridy++;
+        logViewerPanel.add(btnLoadMoreDown, gbc);
+        
+        gbc.gridy++;
+        logViewerPanel.add(Box.createRigidArea(btnLoadMoreUp.getSize()));
+        
+        gbc.gridy++;
+        logViewerPanel.add(btnBookmarkBack, gbc);
+        
+        gbc.gridy++;
+        logViewerPanel.add(btnBookmarkFwd, gbc);
+        
+        gbc.gridy++;
+        logViewerPanel.add(btnBookmarkList, gbc);
+        
+        this.setLayout(new BorderLayout());
+        this.add(pnl, BorderLayout.CENTER);
+        
+        Timer keyTimer = new Timer();
+        keyTimer.scheduleAtFixedRate(new KeystrokeTimer(), KEYSTROKE_RATE, KEYSTROKE_RATE);
+        
+        LogScene.instance = this;
+    }
+    
+    private void initListeners() {
+        txfMethodFilter.addKeyListener(new FilterKeyListener());
+        txfScopeFilter.addKeyListener(new FilterKeyListener());
+        txfNodeFilter.addKeyListener(new FilterKeyListener());
+        txfFulltextFilter.addKeyListener(new FilterKeyListener());
+        
+        txfMethodFilter.addFocusListener(new FilterFocusListener());
+        txfScopeFilter.addFocusListener(new FilterFocusListener());
+        txfNodeFilter.addFocusListener(new FilterFocusListener());
+        txfFulltextFilter.addFocusListener(new FilterFocusListener());
+        
+        btnLoadMoreUp.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent ae) {
+                int line = logViewer.getCurrentlyDisplayedTopLine();
+                int top = logViewer.getCurrentTopLine();
+                int bottom = logViewer.getCurrentBottomLine();
+                logViewer.setLogLines(logModel.range(line, line - top + LOG_LINES, bottom - line), line); 
+            } 
+        });
+        
+        btnLoadMoreDown.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent ae) {
+                int line = logViewer.getCurrentlyDisplayedTopLine();
+                int top = logViewer.getCurrentTopLine();
+                int bottom = logViewer.getCurrentBottomLine();
+                logViewer.setLogLines(logModel.range(line, line - top, bottom - line + LOG_LINES), line); 
+            } 
+        });
+        
+        btnBookmarkBack.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent ae) {
+                int result = logViewer.tryLastBookmark();
+                if (result >= 0) {
+                    tblResult.clearSelection();
+                    logViewer.setLogLines(logModel.range(result, LOG_LINES, LOG_LINES), result); 
+                }
+            }
+        });
+        
+        btnBookmarkFwd.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent ae) {
+                int result = logViewer.tryNextBookmark();
+                if (result >= 0) {
+                    tblResult.clearSelection();
+                    logViewer.setLogLines(logModel.range(result, LOG_LINES, LOG_LINES), result);
+                }
+            }
+        });
+        
+        btnBookmarkList.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent ae) {
+                List<LogLine> bookmarkedLines = logViewer.getBookmarkedLines();
+                if (bookmarkedLines.size() > 0) {
+                    BookmarkDialog bd = new BookmarkDialog(bookmarkedLines, null);
+                    if (bd.getTarget() != null) {
+                        LogLine target = bd.getTarget();
+                        int line = target.getLineNumber();
+                        logViewer.setLogLines(logModel.range(line, LOG_LINES, LOG_LINES), line); 
+                    }
+                } else {
+                    JOptionPane.showMessageDialog(LogScene.this, "No bookmarks set.", "", JOptionPane.INFORMATION_MESSAGE);
+                }
+            }
+        });
+        
+        tblResult.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+            @Override
+            public void valueChanged(ListSelectionEvent lse) {
+                if (tblResult.getSelectedRow() == -1) {
+                    logViewer.clearLogLines();
+                    return;
+                }
+                
+                TableLine selectedLine = tblResultModel.getTableLine(tblResult.getSelectedRow());
+                int firstLine = selectedLine.getFirstLine();
+                int lastLine = selectedLine.getLastLine();
+                
+                if (firstLine == lastLine) { 
+                    // only display selected line
+                    List<LogLine> line = new ArrayList<>();
+                    line.add(selectedLine.getLogLine());
+                    logViewer.setLogLines(line);
+                } else {
+                    // display selected range
+                    int pre = firstLine==lastLine?LOG_LINES:selectedLine.getLogLine().getLineNumber()-firstLine;
+                    int post = firstLine==lastLine?LOG_LINES:lastLine-selectedLine.getLogLine().getLineNumber();
+
+                    logViewer.setLogLines(logModel.range(selectedLine.getLogLine(), pre, post));           
+                }
+            }
+        });
+    }
+    
+    private boolean executeFilters() {
+        if (logStatus == LogStatus.NO_LOG) {
+            loadLogFile();
+            return false;
+        }
+        if (logStatus == LogStatus.LOADING) {
+            return false;
+        }
+
+        boolean execute = trySetFilter(filterManager.getMethodFilter(), txfMethodFilter.getText().trim(), lblMethodFilter);
+        execute = trySetFilter(filterManager.getScopeFilter(), txfScopeFilter.getText().trim(), lblScopeFilter) || execute;
+        try {
+            // node number
+            int node = Integer.parseInt(txfNodeFilter.getText().trim());
+            execute = trySetFilter(filterManager.getNodeFilter(), node, lblNodeFilter) || execute;
+        } catch (Exception e) {
+            // node name
+            execute = trySetFilter(filterManager.getNodeFilter(), txfNodeFilter.getText().trim(), lblNodeFilter) || execute;
+        }
+        execute = trySetFilter(filterManager.getFullTextFilter(), txfFulltextFilter.getText().trim(), lblFulltextFilter) || execute;
+
+        if (!execute)
+            return true;
+        
+        tryInterruptFilter();
+
+        filterRunThread = new Thread(new Runnable() {
+
+            @Override
+            public void run() {
+                try {
+                    List<LogLine> result = filterManager.execute(logModel);
+                    lblIcon.setIcon(null);
+
+                    if (!Thread.interrupted())
+                        buildTableEntries(result);
+                } catch (InterruptedException e) {
+                }
+            }
+
+        });
+        lblIcon.setIcon(IMGICON_LOAD);
+        filterRunThread.start();
+        
+        return true;
+    }
+    
+    private boolean trySetFilter(Filter filter, Object constraint, JLabel marker) {
+        try {
+            filter.setConstraints(constraint);
+            marker.setForeground(Color.BLACK);
+            return constraint != null && (!(constraint instanceof String) || (constraint instanceof String && ((String)constraint).trim().length() > 0));
+        } catch (PatternSyntaxException e) {
+            filter.setConstraints(new Object[]{});
+            marker.setForeground(Color.RED);
+            return false;
+        }
+    }
+    
+    private void tryInterruptFilter() {
+        if (filterRunThread != null && (filterRunThread.isAlive() || !filterRunThread.isInterrupted())) {
+            lblIcon.setIcon(null);
+            filterRunThread.interrupt();
+        }
+    }
+    
+    private void buildTableEntries(List<LogLine> filterResult) {
+        List<TableLine> tableEntries;
+        
+        int methodLength = txfMethodFilter.getText().trim().length();
+        int scopeLength = txfScopeFilter.getText().trim().length();
+        int nodeLength = txfNodeFilter.getText().trim().length();
+        int fulltextLength = txfFulltextFilter.getText().trim().length();
+        
+        boolean preventGrouping = nodeLength != 0 || fulltextLength != 0;
+        
+        if (!preventGrouping && methodLength > 0 && scopeLength == 0) {
+            tableEntries = groupByMethod(filterResult);
+        } else if (!preventGrouping && scopeLength > 0) {
+            tableEntries = groupByScope(filterResult);
+        } else {
+            tableEntries = showAllLines(filterResult);
+        }
+        
+        tblResultModel.setLogEntries(tableEntries);
+        
+        int width = 0;
+        for (int i = 0; i < tableEntries.size(); i++) {
+            TableCellRenderer tcr = tblResult.getCellRenderer(i, 0);
+            Component c = tcr.getTableCellRendererComponent(tblResult, tblResultModel.getValueAt(i, 0), false, false, i, 0);
+            if (c instanceof JLabel) {
+                JLabel l = (JLabel) c;
+                FontMetrics fm = l.getFontMetrics(l.getFont());
+                width = Math.max(width, fm.stringWidth(l.getText()));
+            }
+        }
+       
+        // proper resizing of column
+        // setWidth and setPreferredWidth do not trigger resize
+        TableColumn col = tblResult.getColumnModel().getColumn(0);
+        col.setMinWidth(width+5);
+        col.setMaxWidth(width+5);
+        
+        // reenable resizing for user
+        col.setMinWidth(0);
+        col.setMaxWidth(999);
+    }
+    
+    private List<TableLine> groupByMethod(List<LogLine> filterResult) {
+        List<TableLine> tableEntries = new ArrayList<>();
+        int firstLine = -1;
+        for (int i = 0; i < filterResult.size(); i++) {
+            LogLine line = filterResult.get(i);
+            
+            if (firstLine < 0)
+                firstLine = line.getLineNumber();
+
+            if (i < filterResult.size() - 1) {
+                LogLine next = filterResult.get(i+1);
+                if (line.getMethod() != next.getMethod()) {
+                    tableEntries.add(new TableLine(line, firstLine));
+                    firstLine = next.getLineNumber();
+                }
+            } else {
+                tableEntries.add(new TableLine(line, firstLine));
+            }
+        }
+        return tableEntries;
+    }
+    
+    private List<TableLine> groupByScope(List<LogLine> filterResult) {
+        List<TableLine> tableEntries = new ArrayList<>();
+        LogLine firstScopeLine = null;
+        for (int i = 0; i < filterResult.size(); i++) {
+            LogLine line = filterResult.get(i);
+            
+            if (firstScopeLine == null)
+                firstScopeLine = line;
+
+            if (i < filterResult.size() - 1) {
+                LogLine next = filterResult.get(i+1);
+                if (line.getScope() != next.getScope()) {
+                    tableEntries.add(new TableLine(firstScopeLine, line.getLineNumber()));
+                    firstScopeLine = next;
+                }
+            } else {
+                tableEntries.add(new TableLine(firstScopeLine, line.getLineNumber()));
+            }
+        }
+        return tableEntries;
+    }
+    
+    private List<TableLine> showAllLines(List<LogLine> filterResult) {
+        List<TableLine> tableEntries = new ArrayList<>();
+        for (LogLine line : filterResult) {
+            tableEntries.add(new TableLine(line));
+        }
+        return tableEntries;
+    }
+    
+    public void loadLogFile() {
+        JFileChooser fc = new JFileChooser();
+        fc.setFileFilter(new javax.swing.filechooser.FileFilter() {
+
+            @Override
+            public boolean accept(File f) {
+                return f.isDirectory() ||
+                       f.getName().toLowerCase().endsWith(".txt") ||
+                       f.getName().toLowerCase().endsWith(".log");
+            }
+
+            @Override
+            public String getDescription() {
+                return "Log files (*.txt, *.log)";
+            }
+        });
+        fc.setCurrentDirectory(new File(NbPreferences.forModule(LogScene.class).get(PREFERENCE_DIR, "~")));
+        fc.setDialogTitle("Load log file");
+
+        if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
+            tryInterruptFilter();
+            
+            final File file = fc.getSelectedFile();
+            
+            NbPreferences.forModule(LogScene.class).put(PREFERENCE_DIR, file.getParent());
+            
+            lblIcon.setIcon(IMGICON_LOAD);
+            logStatus = LogStatus.LOADING;
+            new Thread(new Runnable(){
+
+                @Override
+                public void run() {
+                    try {
+                        logModel = parser.parse(file, new LoadProgressMonitor(lblMessage, "Loading file " + file.getName() + "..."));
+                        lblIcon.setIcon(null);
+                        lblMessage.setText("Current logfile: " + file.getName());
+                        logStatus = LogStatus.ACTIVE;
+                    } catch (IOException ex) {
+                        Exceptions.printStackTrace(ex);
+                    }
+                }
+
+            }).start();
+        }
+    }
+    
+    private class FilterKeyListener extends KeyAdapter {
+        @Override
+        public void keyTyped(KeyEvent e) {
+            tryInterruptFilter();
+            timeSinceLastKeystroke = 0;
+        }
+    }
+    
+    private class FilterFocusListener implements FocusListener {
+        private boolean ignore = false;
+        
+        @Override
+        public void focusGained(FocusEvent fe) {
+            if (!ignore && logStatus == LogStatus.NO_LOG) {
+                ignore = true;
+                loadLogFile();
+            }
+        }
+
+        @Override
+        public void focusLost(FocusEvent fe) {
+            if (fe instanceof CausedFocusEvent) {
+                CausedFocusEvent cfe = (CausedFocusEvent) fe;
+                ignore = ignore && // don't change ignore to true if it is already false
+                         cfe.getCause() == CausedFocusEvent.Cause.ACTIVATION; // ACTIVATION is triggered if the
+                                                                              // FileChooser is opened
+            }
+        }
+        
+    }
+    
+    private class KeystrokeTimer extends TimerTask {
+        @Override
+        public void run() {
+            if (timeSinceLastKeystroke < 0)
+                return;
+            
+            timeSinceLastKeystroke += KEYSTROKE_RATE;
+            
+            if (timeSinceLastKeystroke >= KEYSTROKE_TRESHOLD) {
+                int save = timeSinceLastKeystroke;
+                timeSinceLastKeystroke = -1; // needs to be set to -1 to prevent 
+                                             // multiple parallel filter execution
+                
+                if (!executeFilters())
+                    timeSinceLastKeystroke = save;
+            }
+        }
+    }
+    
+    private class LoadProgressMonitor implements ProgressMonitor {
+        private String staticText;
+        private JLabel lblStatus;
+        
+        public LoadProgressMonitor(JLabel lblStatus, String staticText) {
+            this.lblStatus = lblStatus;
+            this.staticText = staticText;
+            
+            lblStatus.setText(staticText);
+        }
+        
+        @Override
+        public void worked(float percentage) {
+            int perc = Math.round(percentage*100);
+            lblStatus.setText(staticText + " (" + perc + " %)");
+        }
+
+        @Override
+        public void finished() {
+            if (parser.hasErrors()) {
+                if (JOptionPane.showConfirmDialog(LogScene.this, "Parsing log file finished with errors. Show error messages?", "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {
+                    List<LogParser.ParseError> errors = parser.getErrors();
+                    ImportLogErrorDialog.showDialog(LogScene.this, errors);
+                }
+            }
+        }
+        
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/actions/ImportLogAction.java	Tue Jul 03 11:16:56 2012 +0200
@@ -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.logviewer.scene.actions;
+
+import com.oracle.graal.visualizer.logviewer.scene.LogScene;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+
+@ActionID(id = "com.oracle.graal.visualizer.logviewer.scene.actions.ImportLogActions", category = "File")
+@ActionRegistration(displayName = "Import Log", iconBase = "com/oracle/graal/visualizer/logviewer/scene/icons/import_log.png")
+@ActionReference(path = "Menu/File", position = 600)
+public class ImportLogAction implements ActionListener {
+
+    @Override
+    public void actionPerformed(ActionEvent ae) {
+        LogScene.getInstance().loadLogFile();
+    }
+}
Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/arrow_down.png has changed
Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/arrow_up.png has changed
Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_back.png has changed
Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_forward.png has changed
Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_list.png has changed
Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/import_log.png has changed
Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/loading.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/model/LogTableModel.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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.logviewer.scene.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.table.AbstractTableModel;
+
+public class LogTableModel extends AbstractTableModel {
+    private final static String[] columnNames = {"Line #", "Method", "Scope", "Node", "Log Text"};
+    
+    private List<TableLine> entries = new ArrayList<>();
+    
+    public void setLogEntries(List<TableLine> entries) {
+        this.entries = entries;
+        fireTableDataChanged();
+    }
+    
+    public TableLine getTableLine(int line) {
+        return entries.get(line);
+    }
+    
+    @Override
+    public int getRowCount() {
+        return entries.size();
+    }
+
+    @Override
+    public int getColumnCount() {
+        return columnNames.length;
+    }
+
+    @Override
+    public String getColumnName(int column) {
+        return columnNames[column];
+    }
+
+    @Override
+    public Object getValueAt(int i, int i1) {
+        switch (i1) {
+            case 0:
+                return entries.get(i).getLineNr();
+            case 1:
+                return entries.get(i).getLogLine().getMethod().getName();
+            case 2:
+                return entries.get(i).getLogLine().getScope()!=null?
+                           entries.get(i).getLogLine().getScope().getName():"";
+            case 3:
+                return entries.get(i).getLogLine().getNode()!=null?
+                           entries.get(i).getLogLine().getNode().getName():"";
+            case 4:
+                return entries.get(i).getLogLine().getText();
+        }
+        return null;
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/model/TableLine.java	Tue Jul 03 11:16:56 2012 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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.logviewer.scene.model;
+
+import com.oracle.graal.visualizer.logviewer.model.LogLine;
+
+public class TableLine {
+
+    private int lineNr;
+    private LogLine logLine;
+    
+    // display single log line
+    public TableLine(LogLine logLine) {
+        this(logLine, logLine.getLineNumber());
+    }
+    
+    // display line number range (from logLine to lineNr or vice versa)
+    public TableLine(LogLine logLine, int lineNr) {
+        this.logLine = logLine;
+        this.lineNr = lineNr;
+    }
+    
+    public int getFirstLine() {
+        return lineNr < logLine.getLineNumber()?lineNr:logLine.getLineNumber();
+    }
+    
+    public int getLastLine() {
+        return lineNr > logLine.getLineNumber()?lineNr:logLine.getLineNumber();
+    }
+    
+    public String getLineNr() {
+        if (lineNr == logLine.getLineNumber()) {
+            return String.valueOf(lineNr);
+        }
+        return getFirstLine() + "-" + getLastLine();
+    }
+    
+    public LogLine getLogLine() {
+        return logLine;
+    }
+}
--- a/visualizer/nbproject/project.properties	Tue Jul 03 11:16:38 2012 +0200
+++ b/visualizer/nbproject/project.properties	Tue Jul 03 11:16:56 2012 +0200
@@ -1,48 +1,50 @@
-app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif
-app.name=graalvisualizer
-app.title=Graal Visualizer
-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
+app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif
+app.name=graalvisualizer
+app.title=Graal Visualizer
+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.com.oracle.graal.visualizer.logviewer}
+project.at.ssw.visualizer.cfg=ControlFlowEditor
+project.com.oracle.graal.visualizer.logviewer=LogViewer
+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