changeset 5042:d0d0dfbebd03

Merge
author Christian Haeubl <christian.haeubl@oracle.com>
date Wed, 07 Mar 2012 10:02:33 -0800
parents e5d42eccfb29 (current diff) 44d746dc51bf (diff)
children 879ac08596b8
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BytecodeLookupSwitch.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BytecodeStream.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BytecodeSwitch.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BytecodeTableSwitch.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/Bytecodes.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/Bytes.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/package-info.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/PlaceholderNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/FrameStateAccess.java
diffstat 34 files changed, 2758 insertions(+), 2880 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSite.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSite.java	Wed Mar 07 10:02:33 2012 -0800
@@ -22,8 +22,6 @@
  */
 package com.oracle.max.cri.xir;
 
-import com.oracle.max.cri.ci.*;
-
 /**
  * Encapsulates the notion of a site where XIR can be supplied. It is supplied to the {@link RiXirGenerator} by the
  * compiler for each place where XIR can be generated. This interface allows a number of queries, including the
@@ -32,13 +30,6 @@
 public interface XirSite {
 
     /**
-     * Gets the {@link CiCodePos code position} associated with this site. This is useful for inserting
-     * instrumentation at the XIR level.
-     * @return the code position if it is available; {@code null} otherwise
-     */
-    CiCodePos getCodePos();
-
-    /**
      * Checks whether the specified argument is guaranteed to be non-null at this site.
      * @param argument the argument
      * @return {@code true} if the argument is non null at this site
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Wed Mar 07 10:02:33 2012 -0800
@@ -187,6 +187,7 @@
     public static boolean OptReorderLoops                    = true;
     public static boolean OptEliminateGuards                 = true;
     public static boolean OptImplicitNullChecks              = true;
+    public static boolean OptLivenessAnalysis                = true;
 
     /**
      * Flag to turn on SSA-based register allocation, which is currently under development.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java	Wed Mar 07 10:02:33 2012 -0800
@@ -27,6 +27,7 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.graal.compiler.gen.LIRGenerator.LockScope;
+import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.lir.*;
 import com.oracle.max.graal.nodes.*;
@@ -106,13 +107,16 @@
     }
 
     private CiFrame computeFrameForState(FrameState state, LockScope locks) {
+        int numLocals = state.localsSize();
+        int numStack = state.stackSize();
         int numLocks = (locks != null && locks.callerState == state.outerFrameState()) ? locks.stateDepth + 1 : 0;
 
-        CiValue[] values = new CiValue[state.valuesSize() + numLocks];
-        int valueIndex = 0;
-
-        for (int i = 0; i < state.valuesSize(); i++) {
-            values[valueIndex++] = toCiValue(state.valueAt(i));
+        CiValue[] values = new CiValue[numLocals + numStack + numLocks];
+        for (int i = 0; i < numLocals; i++) {
+            values[i] = toCiValue(state.localAt(i));
+        }
+        for (int i = 0; i < numStack; i++) {
+            values[numLocals + i] = toCiValue(state.stackAt(i));
         }
 
         LockScope nextLock = locks;
@@ -122,7 +126,7 @@
             CiValue owner = toCiValue(nextLock.monitor.object());
             CiValue lockData = nextLock.lockData;
             boolean eliminated = nextLock.monitor.eliminated();
-            values[state.valuesSize() + nextLock.stateDepth] = new CiMonitorValue(owner, lockData, eliminated);
+            values[numLocals + numStack + nextLock.stateDepth] = new CiMonitorValue(owner, lockData, eliminated);
 
             nextLock = nextLock.outer;
         }
@@ -148,18 +152,22 @@
                 ciObj = CiVirtualObject.get(obj.type(), null, virtualObjects.size());
                 virtualObjects.put(obj, ciObj);
             }
+            Debug.metric("StateVirtualObjects").increment();
             return ciObj;
 
         } else if (value instanceof ConstantNode) {
+            Debug.metric("StateConstants").increment();
             return ((ConstantNode) value).value;
 
         } else if (value != null) {
+            Debug.metric("StateVariables").increment();
             CiValue operand = nodeOperands.get(value);
             assert operand != null && (operand instanceof Variable || operand instanceof CiConstant);
             return operand;
 
         } else {
             // return a dummy value because real value not needed
+            Debug.metric("StateIllegals").increment();
             return CiValue.IllegalValue;
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Mar 07 10:02:33 2012 -0800
@@ -28,7 +28,6 @@
 import static com.oracle.max.cri.util.MemoryBarriers.*;
 import static com.oracle.max.graal.lir.ValueUtil.*;
 
-import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.max.asm.*;
@@ -50,7 +49,11 @@
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.lir.*;
-import com.oracle.max.graal.lir.StandardOp.*;
+import com.oracle.max.graal.lir.StandardOp.JumpOp;
+import com.oracle.max.graal.lir.StandardOp.LabelOp;
+import com.oracle.max.graal.lir.StandardOp.ParametersOp;
+import com.oracle.max.graal.lir.StandardOp.PhiJumpOp;
+import com.oracle.max.graal.lir.StandardOp.PhiLabelOp;
 import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction;
@@ -347,7 +350,7 @@
                 } else {
                     TTY.println("STATE CHANGE (singlePred)");
                     if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
-                        TTY.println(fs.toDetailedString());
+                        TTY.println(fs.toString(Node.Verbosity.Debugger));
                     }
                 }
             }
@@ -395,12 +398,11 @@
             }
             if (stateAfter != null) {
                 lastState = stateAfter;
-                assert checkStartOperands(instr, lastState);
                 assert checkStateReady(lastState);
                 if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
                     TTY.println("STATE CHANGE");
                     if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
-                        TTY.println(stateAfter.toDetailedString());
+                        TTY.println(stateAfter.toString(Node.Verbosity.Debugger));
                     }
                 }
             }
@@ -428,8 +430,7 @@
     private boolean checkStateReady(FrameState state) {
         FrameState fs = state;
         while (fs != null) {
-            for (int i = 0; i < fs.valuesSize(); i++) {
-                ValueNode v = fs.valueAt(i);
+            for (ValueNode v : fs.values()) {
                 if (v != null && !(v instanceof VirtualObjectNode)) {
                     assert operand(v) != null : "Value " + v + " in " + fs + " is not ready!";
                 }
@@ -492,25 +493,6 @@
         }
     }
 
-    private boolean checkStartOperands(Node node, FrameState fs) {
-        if (!Modifier.isNative(method.accessFlags())) {
-            if (node == ((StructuredGraph) node.graph()).start()) {
-                CiKind[] arguments = CiUtil.signatureToKinds(method);
-                int slot = 0;
-                for (CiKind kind : arguments) {
-                    ValueNode arg = fs.localAt(slot);
-                    assert arg != null && arg.kind() == kind.stackKind() : "No valid local in framestate for slot #" + slot + " (" + arg + ")";
-                    slot++;
-                    if (slot < fs.localsSize() && fs.localAt(slot) == null) {
-                        slot++;
-                    }
-                }
-            }
-        }
-        return true;
-    }
-
-
     @Override
     public void visitArrayLength(ArrayLengthNode x) {
         XirArgument array = toXirArgument(x.array());
@@ -1054,7 +1036,15 @@
         FrameState stateAfter = x.stateAfter();
         if (stateAfter != null) {
             // TODO change back to stateBeforeReturn() when RuntimeCallNode uses a CallTargetNode
-            FrameState stateBeforeReturn = stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), x.kind());
+            // (cwi) I made the code that modifies the operand stack conditional. My scenario: runtime calls to, e.g.,
+            // CreateNullPointerException have no equivalent in the bytecodes, so there is in invoke bytecode.
+            // Therefore, the result of the runtime call was never pushed to the stack, and we cannot pop it here.
+            FrameState stateBeforeReturn = stateAfter;
+            if ((stateAfter.stackSize() > 0 && stateAfter.stackAt(stateAfter.stackSize() - 1) == x) ||
+                (stateAfter.stackSize() > 1 && stateAfter.stackAt(stateAfter.stackSize() - 2) == x)) {
+
+                stateBeforeReturn = stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), x.kind());
+            }
 
             // TODO is it correct here that the pointerSlots are not passed to the oop map generation?
             info = stateFor(stateBeforeReturn);
@@ -1451,19 +1441,6 @@
         ValueNode current;
         ValueNode receiver;
 
-        XirSupport() {
-        }
-
-        public CiCodePos getCodePos() {
-            if (current instanceof StateSplit) {
-                FrameState stateAfter = ((StateSplit) current).stateAfter();
-                if (stateAfter != null) {
-                    return stateAfter.toCodePos();
-                }
-            }
-            return null;
-        }
-
         public boolean isNonNull(XirArgument argument) {
             return false;
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java	Wed Mar 07 10:02:33 2012 -0800
@@ -22,10 +22,24 @@
  */
 package com.oracle.max.graal.compiler.phases;
 
+import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.nodes.spi.*;
+import com.oracle.max.graal.nodes.type.*;
 
 public class InsertStateAfterPlaceholderPhase extends Phase {
 
+    private static class PlaceholderNode extends AbstractStateSplit implements Node.IterableNodeType, LIRLowerable {
+        public PlaceholderNode() {
+            super(StampFactory.illegal());
+        }
+
+        @Override
+        public void generate(LIRGeneratorTool gen) {
+            // nothing to do
+        }
+    }
+
     @Override
     protected void run(StructuredGraph graph) {
         for (ReturnNode ret : graph.getNodes(ReturnNode.class)) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Wed Mar 07 10:02:33 2012 -0800
@@ -55,6 +55,7 @@
                 if (dumpGraph) {
                     Debug.dump(graph, "After phase %s", name);
                 }
+                assert graph.verify();
             }
         });
     }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java	Wed Mar 07 10:02:33 2012 -0800
@@ -39,7 +39,7 @@
     private final String meterFilter;
     private final String timerFilter;
     private final String dumpFilter;
-    private final String methodFilter;
+    private final String[] methodFilter;
     private final List<DebugDumpHandler> dumpHandlers = new ArrayList<>();
 
     public HotSpotDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter) {
@@ -47,7 +47,7 @@
         this.meterFilter = meterFilter;
         this.timerFilter = timerFilter;
         this.dumpFilter = dumpFilter;
-        this.methodFilter = methodFilter;
+        this.methodFilter = methodFilter == null ? null : methodFilter.split(",");
         dumpHandlers.add(new IdealGraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintIdealGraphPort));
         dumpHandlers.add(new CFGPrinterObserver());
     }
@@ -89,9 +89,11 @@
         } else {
             for (Object o : Debug.context()) {
                 if (o instanceof RiMethod) {
-                    RiMethod riMethod = (RiMethod) o;
-                    if (CiUtil.format("%H.%n", riMethod).contains(methodFilter)) {
-                        return true;
+                    String methodName = CiUtil.format("%H.%n", (RiMethod) o);
+                    for (String filter : methodFilter) {
+                        if (methodName.contains(filter)) {
+                            return true;
+                        }
                     }
                 }
             }
@@ -107,7 +109,7 @@
         add(sb, "Meter", meterFilter);
         add(sb, "Time", timerFilter);
         add(sb, "Dump", dumpFilter);
-        add(sb, "MethodFilter", methodFilter);
+        add(sb, "MethodFilter", Arrays.toString(methodFilter));
         return sb.toString();
     }
 
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Wed Mar 07 10:02:33 2012 -0800
@@ -30,7 +30,7 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.criutils.*;
-import com.oracle.max.graal.java.*;
+import com.oracle.max.graal.java.bytecode.*;
 
 /**
  * Implementation of RiMethod for resolved HotSpot methods.
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java	Wed Mar 07 10:02:33 2012 -0800
@@ -437,7 +437,7 @@
 
     private CiTargetMethod createCallbackStub(RiResolvedMethod method, CiGenericCallback callback) {
         StructuredGraph graph = new StructuredGraph();
-        FrameStateBuilder frameState = new FrameStateBuilder(method, method.maxLocals(), method.maxStackSize(), graph, false);
+        FrameStateBuilder frameState = new FrameStateBuilder(method, graph, false);
         ValueNode local0 = frameState.loadLocal(0);
 
         FrameState initialFrameState = frameState.create(0);
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BciBlockMapping.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BciBlockMapping.java	Wed Mar 07 10:02:33 2012 -0800
@@ -22,13 +22,17 @@
  */
 package com.oracle.max.graal.java;
 
-import static com.oracle.max.graal.java.Bytecodes.*;
+import static com.oracle.max.graal.java.bytecode.Bytecodes.*;
 
 import java.util.*;
 
+
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.java.bytecode.*;
 import com.oracle.max.graal.nodes.*;
 
 /**
@@ -121,6 +125,7 @@
         public int blockID;
 
         public FixedWithNextNode firstInstruction;
+        public FrameStateBuilder entryState;
 
         public ArrayList<Block> successors = new ArrayList<>(2);
         public int normalSuccessors;
@@ -136,6 +141,11 @@
         public Block retSuccessor;
         public boolean endsWithRet = false;
 
+        public BitMap localsLiveIn;
+        public BitMap localsLiveOut;
+        private BitMap localsLiveGen;
+        private BitMap localsLiveKill;
+
         public Block copy() {
             try {
                 Block block = (Block) super.clone();
@@ -169,12 +179,6 @@
         public int deoptBci;
     }
 
-    public static class DeoptBlock extends Block {
-        public DeoptBlock(int startBci) {
-            this.startBci = startBci;
-        }
-    }
-
     /**
      * The blocks found in this method, in reverse postorder.
      */
@@ -182,6 +186,8 @@
 
     public final RiResolvedMethod method;
 
+    private final BytecodeStream stream;
+
     private final RiExceptionHandler[] exceptionHandlers;
 
     private Block[] blockMap;
@@ -201,6 +207,7 @@
     public BciBlockMapping(RiResolvedMethod method, boolean useBranchPrediction) {
         this.method = method;
         exceptionHandlers = method.exceptionHandlers();
+        stream = new BytecodeStream(method.code());
         this.blockMap = new Block[method.codeSize()];
         this.canTrap = new BitSet(blockMap.length);
         this.blocks = new ArrayList<>();
@@ -232,6 +239,15 @@
 
         // Discard big arrays so that they can be GCed
         blockMap = null;
+
+        if (GraalOptions.OptLivenessAnalysis) {
+            Debug.scope("LivenessAnalysis", new Runnable() {
+                @Override
+                public void run() {
+                    computeLiveness();
+                }
+            });
+        }
     }
 
     private void initializeBlockIds() {
@@ -252,11 +268,12 @@
         // iterate over the bytecodes top to bottom.
         // mark the entrypoints of basic blocks and build lists of successors for
         // all bytecodes that end basic blocks (i.e. goto, ifs, switches, throw, jsr, returns, ret)
-        byte[] code = method.code();
         RiProfilingInfo profilingInfo = method.profilingInfo();
         Block current = null;
-        int bci = 0;
-        while (bci < code.length) {
+        stream.setBCI(0);
+        while (stream.currentBC() != Bytecodes.END) {
+            int bci = stream.currentBCI();
+
             if (current == null || blockMap[bci] != null) {
                 Block b = makeBlock(bci);
                 if (current != null) {
@@ -267,8 +284,7 @@
             blockMap[bci] = current;
             current.endBci = bci;
 
-            int opcode = Bytes.beU1(code, bci);
-            switch (opcode) {
+            switch (stream.currentBC()) {
                 case IRETURN: // fall through
                 case LRETURN: // fall through
                 case FRETURN: // fall through
@@ -300,43 +316,37 @@
                 case IFNULL:    // fall through
                 case IFNONNULL: {
                     current = null;
-                    double probability = useBranchPrediction ? profilingInfo.getBranchTakenProbability(bci) : -1;
-
-                    Block b1 = probability == 0.0 ? new DeoptBlock(bci + Bytes.beS2(code, bci + 1)) : makeBlock(bci + Bytes.beS2(code, bci + 1));
-                    Block b2 = probability == 1.0 ? new DeoptBlock(bci + 3) : makeBlock(bci + 3);
-                    setSuccessors(bci, b1, b2);
+                    setSuccessors(bci, makeBlock(stream.readBranchDest()), makeBlock(stream.nextBCI()));
                     break;
                 }
                 case GOTO:
                 case GOTO_W: {
                     current = null;
-                    int target = bci + Bytes.beSVar(code, bci + 1, opcode == GOTO_W);
-                    Block b1 = makeBlock(target);
-                    setSuccessors(bci, b1);
+                    setSuccessors(bci, makeBlock(stream.readBranchDest()));
                     break;
                 }
                 case TABLESWITCH: {
                     current = null;
-                    BytecodeTableSwitch sw = new BytecodeTableSwitch(code, bci);
+                    BytecodeTableSwitch sw = new BytecodeTableSwitch(stream, bci);
                     setSuccessors(bci, makeSwitchSuccessors(sw));
                     break;
                 }
                 case LOOKUPSWITCH: {
                     current = null;
-                    BytecodeLookupSwitch sw = new BytecodeLookupSwitch(code, bci);
+                    BytecodeLookupSwitch sw = new BytecodeLookupSwitch(stream, bci);
                     setSuccessors(bci, makeSwitchSuccessors(sw));
                     break;
                 }
                 case JSR:
                 case JSR_W: {
                     hasJsrBytecodes = true;
-                    int target = bci + Bytes.beSVar(code, bci + 1, opcode == JSR_W);
+                    int target = stream.readBranchDest();
                     if (target == 0) {
                         throw new JsrNotSupportedBailout("jsr target bci 0 not allowed");
                     }
                     Block b1 = makeBlock(target);
                     current.jsrSuccessor = b1;
-                    current.jsrReturnBci = bci + lengthOf(opcode);
+                    current.jsrReturnBci = stream.nextBCI();
                     current = null;
                     setSuccessors(bci, b1);
                     break;
@@ -346,66 +356,42 @@
                     current = null;
                     break;
                 }
-                case WIDE: {
-                    int opcode2 = Bytes.beU1(code, bci);
-                    switch (opcode2) {
-                        case RET: {
-                            current.endsWithRet = true;
-                            current = null;
-                            break;
-                        }
-                    }
-                    break;
-                }
                 case INVOKEINTERFACE:
                 case INVOKESPECIAL:
                 case INVOKESTATIC:
                 case INVOKEVIRTUAL: {
                     current = null;
-                    int target = bci + lengthOf(code, bci);
-                    Block b1 = makeBlock(target);
-                    setSuccessors(bci, b1);
+                    setSuccessors(bci, makeBlock(stream.nextBCI()));
                     canTrap.set(bci);
                     break;
                 }
-                default: {
-                    if (canTrap(opcode, bci, profilingInfo)) {
+                case IASTORE:
+                case LASTORE:
+                case FASTORE:
+                case DASTORE:
+                case AASTORE:
+                case BASTORE:
+                case CASTORE:
+                case SASTORE:
+                case IALOAD:
+                case LALOAD:
+                case FALOAD:
+                case DALOAD:
+                case AALOAD:
+                case BALOAD:
+                case CALOAD:
+                case SALOAD:
+                case PUTFIELD:
+                case GETFIELD: {
+                    if (GraalOptions.AllowExplicitExceptionChecks && profilingInfo.getExceptionSeen(bci) != RiExceptionSeen.FALSE) {
                         canTrap.set(bci);
                     }
                 }
             }
-            bci += lengthOf(code, bci);
+            stream.next();
         }
     }
 
-    private static boolean canTrap(int opcode, int bci, RiProfilingInfo profilingInfo) {
-        switch (opcode) {
-            case IASTORE:
-            case LASTORE:
-            case FASTORE:
-            case DASTORE:
-            case AASTORE:
-            case BASTORE:
-            case CASTORE:
-            case SASTORE:
-            case IALOAD:
-            case LALOAD:
-            case FALOAD:
-            case DALOAD:
-            case AALOAD:
-            case BALOAD:
-            case CALOAD:
-            case SALOAD:
-            case PUTFIELD:
-            case GETFIELD: {
-                if (GraalOptions.AllowExplicitExceptionChecks) {
-                    return profilingInfo.getExceptionSeen(bci) != RiExceptionSeen.FALSE;
-                }
-            }
-        }
-        return false;
-    }
-
     private Block makeBlock(int startBci) {
         Block oldBlock = blockMap[startBci];
         if (oldBlock == null) {
@@ -471,6 +457,7 @@
             block.successors.add(block.retSuccessor);
             assert block.retSuccessor != block.jsrSuccessor;
         }
+        Debug.log("JSR alternatives block %s  sux %s  jsrSux %s  retSux %s  jsrScope %s", block, block.successors, block.jsrSuccessor, block.retSuccessor, block.jsrScope);
 
         if (block.jsrSuccessor != null || !scope.isEmpty()) {
             for (int i = 0; i < block.successors.size(); i++) {
@@ -482,7 +469,7 @@
                 if (successor == block.retSuccessor) {
                     nextScope = scope.pop();
                 }
-                if (!successor.jsrScope.isEmpty()) {
+                if (!successor.jsrScope.isPrefixOf(nextScope)) {
                     throw new JsrNotSupportedBailout("unstructured control flow  (" + successor.jsrScope + " " + nextScope + ")");
                 }
                 if (!nextScope.isEmpty()) {
@@ -640,4 +627,187 @@
 
         return loops;
     }
+
+
+    private void computeLiveness() {
+        for (Block block : blocks) {
+            computeLocalLiveness(block);
+        }
+
+        boolean changed;
+        int iteration = 0;
+        do {
+            Debug.log("Iteration %d", iteration);
+            changed = false;
+            for (int i = blocks.size() - 1; i >= 0; i--) {
+                Block block = blocks.get(i);
+                Debug.log("  start B%d  [%d, %d]  in: %s  out: %s  gen: %s  kill: %s", block.blockID, block.startBci, block.endBci, block.localsLiveIn, block.localsLiveOut, block.localsLiveGen, block.localsLiveKill);
+
+                boolean blockChanged = (iteration == 0);
+                for (Block sux : block.successors) {
+                    Debug.log("    Successor B%d: %s", sux.blockID, sux.localsLiveIn);
+                    blockChanged = block.localsLiveOut.setUnionWithResult(sux.localsLiveIn) || blockChanged;
+                }
+
+                if (blockChanged) {
+                    block.localsLiveIn.setFrom(block.localsLiveOut);
+                    block.localsLiveIn.setDifference(block.localsLiveKill);
+                    block.localsLiveIn.setUnion(block.localsLiveGen);
+
+                    for (Block sux : block.successors) {
+                        if (sux instanceof ExceptionBlock) {
+                            // Exception handler blocks can be reached from anywhere within the block jumping to them,
+                            // so we conservatively assume local variables require by the exception handler are live both
+                            // at the beginning and end of the block.
+                            blockChanged = block.localsLiveIn.setUnionWithResult(sux.localsLiveIn) || blockChanged;
+                        }
+                    }
+                    Debug.log("  end   B%d  [%d, %d]  in: %s  out: %s  gen: %s  kill: %s", block.blockID, block.startBci, block.endBci, block.localsLiveIn, block.localsLiveOut, block.localsLiveGen, block.localsLiveKill);
+                }
+                changed |= blockChanged;
+            }
+            iteration++;
+        } while (changed);
+    }
+
+    private void computeLocalLiveness(Block block) {
+        block.localsLiveIn = new BitMap(method.maxLocals());
+        block.localsLiveOut = new BitMap(method.maxLocals());
+        block.localsLiveGen = new BitMap(method.maxLocals());
+        block.localsLiveKill = new BitMap(method.maxLocals());
+
+        if (block.startBci < 0 || block.endBci < 0) {
+            return;
+        }
+
+        stream.setBCI(block.startBci);
+        while (stream.currentBCI() <= block.endBci) {
+            switch (stream.currentBC()) {
+                case RETURN:
+                    if (method.isConstructor() && method.holder().superType() == null) {
+                        // return from Object.init implicitly registers a finalizer
+                        // for the receiver if needed, so keep it alive.
+                        loadOne(block, 0);
+                    }
+                    break;
+
+                case LLOAD:
+                case DLOAD:
+                    loadTwo(block, stream.readLocalIndex());
+                    break;
+                case LLOAD_0:
+                case DLOAD_0:
+                    loadTwo(block, 0);
+                    break;
+                case LLOAD_1:
+                case DLOAD_1:
+                    loadTwo(block, 1);
+                    break;
+                case LLOAD_2:
+                case DLOAD_2:
+                    loadTwo(block, 2);
+                    break;
+                case LLOAD_3:
+                case DLOAD_3:
+                    loadTwo(block, 3);
+                    break;
+                case ILOAD:
+                case IINC:
+                case FLOAD:
+                case ALOAD:
+                case RET:
+                    loadOne(block, stream.readLocalIndex());
+                    break;
+                case ILOAD_0:
+                case FLOAD_0:
+                case ALOAD_0:
+                    loadOne(block, 0);
+                    break;
+                case ILOAD_1:
+                case FLOAD_1:
+                case ALOAD_1:
+                    loadOne(block, 1);
+                    break;
+                case ILOAD_2:
+                case FLOAD_2:
+                case ALOAD_2:
+                    loadOne(block, 2);
+                    break;
+                case ILOAD_3:
+                case FLOAD_3:
+                case ALOAD_3:
+                    loadOne(block, 3);
+                    break;
+
+                case LSTORE:
+                case DSTORE:
+                    storeTwo(block, stream.readLocalIndex());
+                    break;
+                case LSTORE_0:
+                case DSTORE_0:
+                    storeTwo(block, 0);
+                    break;
+                case LSTORE_1:
+                case DSTORE_1:
+                    storeTwo(block, 1);
+                    break;
+                case LSTORE_2:
+                case DSTORE_2:
+                    storeTwo(block, 2);
+                    break;
+                case LSTORE_3:
+                case DSTORE_3:
+                    storeTwo(block, 3);
+                    break;
+                case ISTORE:
+                case FSTORE:
+                case ASTORE:
+                    storeOne(block, stream.readLocalIndex());
+                    break;
+                case ISTORE_0:
+                case FSTORE_0:
+                case ASTORE_0:
+                    storeOne(block, 0);
+                    break;
+                case ISTORE_1:
+                case FSTORE_1:
+                case ASTORE_1:
+                    storeOne(block, 1);
+                    break;
+                case ISTORE_2:
+                case FSTORE_2:
+                case ASTORE_2:
+                    storeOne(block, 2);
+                    break;
+                case ISTORE_3:
+                case FSTORE_3:
+                case ASTORE_3:
+                    storeOne(block, 3);
+                    break;
+            }
+            stream.next();
+        }
+    }
+
+    private static void loadTwo(Block block, int local) {
+        loadOne(block, local);
+        loadOne(block, local + 1);
+    }
+
+    private static void loadOne(Block block, int local) {
+        if (!block.localsLiveKill.get(local)) {
+            block.localsLiveGen.set(local);
+        }
+    }
+
+    private static void storeTwo(Block block, int local) {
+        storeOne(block, local);
+        storeOne(block, local + 1);
+    }
+
+    private static void storeOne(Block block, int local) {
+        if (!block.localsLiveGen.get(local)) {
+            block.localsLiveKill.set(local);
+        }
+    }
 }
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BytecodeLookupSwitch.java	Wed Mar 07 09:50:36 2012 -0800
+++ /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.graal.java;
-
-/**
- * A utility for processing {@link Bytecodes#LOOKUPSWITCH} bytecodes.
- */
-class BytecodeLookupSwitch extends BytecodeSwitch {
-    private static final int OFFSET_TO_NUMBER_PAIRS = 4;
-    private static final int OFFSET_TO_FIRST_PAIR_MATCH = 8;
-    private static final int OFFSET_TO_FIRST_PAIR_OFFSET = 12;
-    private static final int PAIR_SIZE = 8;
-
-    /**
-     * Constructor for a {@link BytecodeStream}.
-     * @param stream the {@code BytecodeStream} containing the switch instruction
-     * @param bci the index in the stream of the switch instruction
-     */
-    public BytecodeLookupSwitch(BytecodeStream stream, int bci) {
-        super(stream, bci);
-    }
-
-    /**
-     * Constructor for a bytecode array.
-     * @param code the bytecode array containing the switch instruction.
-     * @param bci the index in the array of the switch instruction
-     */
-    public BytecodeLookupSwitch(byte[] code, int bci) {
-        super(code, bci);
-    }
-
-    @Override
-    public int defaultOffset() {
-        return readWord(alignedBci);
-    }
-
-    @Override
-    public int offsetAt(int i) {
-        return readWord(alignedBci + OFFSET_TO_FIRST_PAIR_OFFSET + PAIR_SIZE * i);
-    }
-
-    @Override
-    public int keyAt(int i) {
-        return readWord(alignedBci + OFFSET_TO_FIRST_PAIR_MATCH + PAIR_SIZE * i);
-    }
-
-    @Override
-    public int numberOfCases() {
-        return readWord(alignedBci + OFFSET_TO_NUMBER_PAIRS);
-    }
-
-    @Override
-    public int size() {
-        return alignedBci + OFFSET_TO_FIRST_PAIR_MATCH + PAIR_SIZE * numberOfCases() - bci;
-    }
-}
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BytecodeStream.java	Wed Mar 07 09:50:36 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.java;
-
-/**
- * A utility class that makes iterating over bytecodes and reading operands
- * simpler and less error prone. For example, it handles the {@link Bytecodes#WIDE} instruction
- * and wide variants of instructions internally.
- */
-public final class BytecodeStream {
-
-    private final byte[] code;
-    private int opcode;
-    private int curBCI;
-    private int nextBCI;
-
-    /**
-     * Creates a new {@code BytecodeStream} for the specified bytecode.
-     * @param code the array of bytes that contains the bytecode
-     */
-    public BytecodeStream(byte[] code) {
-        assert code != null;
-        this.code = code;
-        setBCI(0);
-    }
-
-    /**
-     * Advances to the next bytecode.
-     */
-    public void next() {
-        setBCI(nextBCI);
-    }
-
-    /**
-     * Gets the next bytecode index (no side-effects).
-     * @return the next bytecode index
-     */
-    public int nextBCI() {
-        return nextBCI;
-    }
-
-    /**
-     * Gets the current bytecode index.
-     * @return the current bytecode index
-     */
-    public int currentBCI() {
-        return curBCI;
-    }
-
-    /**
-     * Gets the bytecode index of the end of the code.
-     * @return the index of the end of the code
-     */
-    public int endBCI() {
-        return code.length;
-    }
-
-    /**
-     * Gets the current opcode. This method will never return the
-     * {@link Bytecodes#WIDE WIDE} opcode, but will instead
-     * return the opcode that is modified by the {@code WIDE} opcode.
-     * @return the current opcode; {@link Bytecodes#END} if at or beyond the end of the code
-     */
-    public int currentBC() {
-        if (opcode == Bytecodes.WIDE) {
-            return Bytes.beU1(code, curBCI + 1);
-        } else {
-            return opcode;
-        }
-    }
-
-    /**
-     * Reads the index of a local variable for one of the load or store instructions.
-     * The WIDE modifier is handled internally.
-     * @return the index of the local variable
-     */
-    public int readLocalIndex() {
-        // read local variable index for load/store
-        if (opcode == Bytecodes.WIDE) {
-            return Bytes.beU2(code, curBCI + 2);
-        }
-        return Bytes.beU1(code, curBCI + 1);
-    }
-
-    /**
-     * Read the delta for an {@link Bytecodes#IINC} bytecode.
-     * @return the delta for the {@code IINC}
-     */
-    public int readIncrement() {
-        // read the delta for the iinc bytecode
-        if (opcode == Bytecodes.WIDE) {
-            return Bytes.beS2(code, curBCI + 4);
-        }
-        return Bytes.beS1(code, curBCI + 2);
-    }
-
-    /**
-     * Read the destination of a {@link Bytecodes#GOTO} or {@code IF} instructions.
-     * @return the destination bytecode index
-     */
-    public int readBranchDest() {
-        // reads the destination for a branch bytecode
-        return curBCI + Bytes.beS2(code, curBCI + 1);
-    }
-
-    /**
-     * Read the destination of a {@link Bytecodes#GOTO_W} or {@link Bytecodes#JSR_W} instructions.
-     * @return the destination bytecode index
-     */
-    public int readFarBranchDest() {
-        // reads the destination for a wide branch bytecode
-        return curBCI + Bytes.beS4(code, curBCI + 1);
-    }
-
-    /**
-     * Read a signed 4-byte integer from the bytecode stream at the specified bytecode index.
-     * @param bci the bytecode index
-     * @return the integer value
-     */
-    public int readInt(int bci) {
-        // reads a 4-byte signed value
-        return Bytes.beS4(code, bci);
-    }
-
-    /**
-     * Reads an unsigned, 1-byte value from the bytecode stream at the specified bytecode index.
-     * @param bci the bytecode index
-     * @return the byte
-     */
-    public int readUByte(int bci) {
-        return Bytes.beU1(code, bci);
-    }
-
-    /**
-     * Reads a constant pool index for the current instruction.
-     * @return the constant pool index
-     */
-    public char readCPI() {
-        if (opcode == Bytecodes.LDC) {
-            return (char) Bytes.beU1(code, curBCI + 1);
-        }
-        return (char) Bytes.beU2(code, curBCI + 1);
-    }
-
-    /**
-     * Reads a signed, 1-byte value for the current instruction (e.g. BIPUSH).
-     * @return the byte
-     */
-    public byte readByte() {
-        return code[curBCI + 1];
-    }
-
-    /**
-     * Reads a signed, 2-byte short for the current instruction (e.g. SIPUSH).
-     * @return the short value
-     */
-    public short readShort() {
-        return (short) Bytes.beS2(code, curBCI + 1);
-    }
-
-    /**
-     * Sets the bytecode index to the specified value.
-     * If {@code bci} is beyond the end of the array, {@link #currentBC} will return
-     * {@link Bytecodes#END} and other methods may throw {@link ArrayIndexOutOfBoundsException}.
-     * @param bci the new bytecode index
-     */
-    public void setBCI(int bci) {
-        curBCI = bci;
-        if (curBCI < code.length) {
-            opcode = Bytes.beU1(code, bci);
-            nextBCI = bci + Bytecodes.lengthOf(code, bci);
-        } else {
-            opcode = Bytecodes.END;
-            nextBCI = curBCI;
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BytecodeSwitch.java	Wed Mar 07 09:50:36 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.java;
-
-/**
- * An abstract class that provides the state and methods common to {@link Bytecodes#LOOKUPSWITCH}
- * and {@link Bytecodes#TABLESWITCH} instructions.
- */
-public abstract class BytecodeSwitch {
-    /**
-     * The {@link BytecodeStream} containing bytecode array or {@code null} if {@link #code} is not {@code null}.
-     */
-    private final BytecodeStream stream;
-    /**
-     * The bytecode array or {@code null} if {@link #stream} is not {@code null}.
-     */
-    private final byte[] code;
-    /**
-     * Index of start of switch instruction.
-     */
-    protected final int bci;
-    /**
-     * Index of the start of the additional data for the switch instruction, aligned to a multiple of four from the method start.
-     */
-    protected final int alignedBci;
-
-    /**
-     * Constructor for a {@link BytecodeStream}.
-     * @param stream the {@code BytecodeStream} containing the switch instruction
-     * @param bci the index in the stream of the switch instruction
-     */
-    public BytecodeSwitch(BytecodeStream stream, int bci) {
-        this.alignedBci = (bci + 4) & 0xfffffffc;
-        this.stream = stream;
-        this.code = null;
-        this.bci = bci;
-    }
-
-    /**
-     * Constructor for a bytecode array.
-     * @param code the bytecode array containing the switch instruction.
-     * @param bci the index in the array of the switch instruction
-     */
-    public BytecodeSwitch(byte[] code, int bci) {
-        this.alignedBci = (bci + 4) & 0xfffffffc;
-        this.stream = null;
-        this.code = code;
-        this.bci = bci;
-    }
-
-    /**
-     * Gets the current bytecode index.
-     * @return the current bytecode index
-     */
-    public int bci() {
-        return bci;
-    }
-
-    /**
-     * Gets the index of the instruction denoted by the {@code i}'th switch target.
-     * @param i index of the switch target
-     * @return the index of the instruction denoted by the {@code i}'th switch target
-     */
-    public int targetAt(int i) {
-        return bci + offsetAt(i);
-    }
-
-    /**
-     * Gets the index of the instruction for the default switch target.
-     * @return the index of the instruction for the default switch target
-     */
-    public int defaultTarget() {
-        return bci + defaultOffset();
-    }
-
-    /**
-     * 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();
-
-    /**
-     * Gets the key at {@code i}'th switch target index.
-     * @param i the switch target index
-     * @return the key at {@code i}'th switch target index
-     */
-    public abstract int keyAt(int i);
-
-    /**
-     * Gets the offset from the start of the switch instruction for the {@code i}'th switch target.
-     * @param i the switch target index
-     * @return the offset to the {@code i}'th switch target
-     */
-    public abstract int offsetAt(int i);
-
-    /**
-     * Gets the number of switch targets.
-     * @return the number of switch targets
-     */
-    public abstract int numberOfCases();
-
-    /**
-     * Gets the total size in bytes of the switch instruction.
-     * @return the total size in bytes of the switch instruction
-     */
-    public abstract int size();
-
-    /**
-     * Reads the signed value at given bytecode index.
-     * @param readBci the start index of the value to retrieve
-     * @return the signed, 4-byte value in the bytecode array starting at {@code bci}
-     */
-    protected int readWord(int readBci) {
-        if (code != null) {
-            return Bytes.beS4(code, readBci);
-        }
-        return stream.readInt(readBci);
-    }
-}
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BytecodeTableSwitch.java	Wed Mar 07 09:50:36 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.java;
-
-/**
- * A utility for processing {@link Bytecodes#TABLESWITCH} bytecodes.
- */
-public class BytecodeTableSwitch extends BytecodeSwitch {
-    private static final int OFFSET_TO_LOW_KEY = 4;
-    private static final int OFFSET_TO_HIGH_KEY = 8;
-    private static final int OFFSET_TO_FIRST_JUMP_OFFSET = 12;
-    private static final int JUMP_OFFSET_SIZE = 4;
-
-    /**
-     * Constructor for a {@link BytecodeStream}.
-     * @param stream the {@code BytecodeStream} containing the switch instruction
-     * @param bci the index in the stream of the switch instruction
-     */
-    public BytecodeTableSwitch(BytecodeStream stream, int bci) {
-        super(stream, bci);
-    }
-
-    /**
-     * Constructor for a bytecode array.
-     * @param code the bytecode array containing the switch instruction.
-     * @param bci the index in the array of the switch instruction
-     */
-    public BytecodeTableSwitch(byte[] code, int bci) {
-        super(code, bci);
-    }
-
-    /**
-     * Gets the low key of the table switch.
-     * @return the low key
-     */
-    public int lowKey() {
-        return readWord(alignedBci + OFFSET_TO_LOW_KEY);
-    }
-
-    /**
-     * Gets the high key of the table switch.
-     * @return the high key
-     */
-    public int highKey() {
-        return readWord(alignedBci + OFFSET_TO_HIGH_KEY);
-    }
-
-    @Override
-    public int keyAt(int i) {
-        return lowKey() + i;
-    }
-
-    @Override
-    public int defaultOffset() {
-        return readWord(alignedBci);
-    }
-
-    @Override
-    public int offsetAt(int i) {
-        return readWord(alignedBci + OFFSET_TO_FIRST_JUMP_OFFSET + JUMP_OFFSET_SIZE * i);
-    }
-
-    @Override
-    public int numberOfCases() {
-        return highKey() - lowKey() + 1;
-    }
-
-    @Override
-    public int size() {
-        return alignedBci + OFFSET_TO_FIRST_JUMP_OFFSET + JUMP_OFFSET_SIZE * numberOfCases() - bci;
-    }
-}
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/Bytecodes.java	Wed Mar 07 09:50:36 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,976 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.java;
-
-import static com.oracle.max.graal.java.Bytecodes.Flags.*;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.regex.*;
-
-/**
- * The definitions of the bytecodes that are valid input to the compiler and
- * related utility methods. This comprises two groups: the standard Java
- * bytecodes defined by <a href=
- * "http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html">
- * Java Virtual Machine Specification</a>, and a set of <i>extended</i>
- * bytecodes that support low-level programming, for example, memory barriers.
- *
- * The extended bytecodes are one or three bytes in size. The one-byte bytecodes
- * follow the values in the standard set, with no gap. The three-byte extended
- * bytecodes share a common first byte and carry additional instruction-specific
- * information in the second and third bytes.
- */
-public class Bytecodes {
-    public static final int NOP                  =   0; // 0x00
-    public static final int ACONST_NULL          =   1; // 0x01
-    public static final int ICONST_M1            =   2; // 0x02
-    public static final int ICONST_0             =   3; // 0x03
-    public static final int ICONST_1             =   4; // 0x04
-    public static final int ICONST_2             =   5; // 0x05
-    public static final int ICONST_3             =   6; // 0x06
-    public static final int ICONST_4             =   7; // 0x07
-    public static final int ICONST_5             =   8; // 0x08
-    public static final int LCONST_0             =   9; // 0x09
-    public static final int LCONST_1             =  10; // 0x0A
-    public static final int FCONST_0             =  11; // 0x0B
-    public static final int FCONST_1             =  12; // 0x0C
-    public static final int FCONST_2             =  13; // 0x0D
-    public static final int DCONST_0             =  14; // 0x0E
-    public static final int DCONST_1             =  15; // 0x0F
-    public static final int BIPUSH               =  16; // 0x10
-    public static final int SIPUSH               =  17; // 0x11
-    public static final int LDC                  =  18; // 0x12
-    public static final int LDC_W                =  19; // 0x13
-    public static final int LDC2_W               =  20; // 0x14
-    public static final int ILOAD                =  21; // 0x15
-    public static final int LLOAD                =  22; // 0x16
-    public static final int FLOAD                =  23; // 0x17
-    public static final int DLOAD                =  24; // 0x18
-    public static final int ALOAD                =  25; // 0x19
-    public static final int ILOAD_0              =  26; // 0x1A
-    public static final int ILOAD_1              =  27; // 0x1B
-    public static final int ILOAD_2              =  28; // 0x1C
-    public static final int ILOAD_3              =  29; // 0x1D
-    public static final int LLOAD_0              =  30; // 0x1E
-    public static final int LLOAD_1              =  31; // 0x1F
-    public static final int LLOAD_2              =  32; // 0x20
-    public static final int LLOAD_3              =  33; // 0x21
-    public static final int FLOAD_0              =  34; // 0x22
-    public static final int FLOAD_1              =  35; // 0x23
-    public static final int FLOAD_2              =  36; // 0x24
-    public static final int FLOAD_3              =  37; // 0x25
-    public static final int DLOAD_0              =  38; // 0x26
-    public static final int DLOAD_1              =  39; // 0x27
-    public static final int DLOAD_2              =  40; // 0x28
-    public static final int DLOAD_3              =  41; // 0x29
-    public static final int ALOAD_0              =  42; // 0x2A
-    public static final int ALOAD_1              =  43; // 0x2B
-    public static final int ALOAD_2              =  44; // 0x2C
-    public static final int ALOAD_3              =  45; // 0x2D
-    public static final int IALOAD               =  46; // 0x2E
-    public static final int LALOAD               =  47; // 0x2F
-    public static final int FALOAD               =  48; // 0x30
-    public static final int DALOAD               =  49; // 0x31
-    public static final int AALOAD               =  50; // 0x32
-    public static final int BALOAD               =  51; // 0x33
-    public static final int CALOAD               =  52; // 0x34
-    public static final int SALOAD               =  53; // 0x35
-    public static final int ISTORE               =  54; // 0x36
-    public static final int LSTORE               =  55; // 0x37
-    public static final int FSTORE               =  56; // 0x38
-    public static final int DSTORE               =  57; // 0x39
-    public static final int ASTORE               =  58; // 0x3A
-    public static final int ISTORE_0             =  59; // 0x3B
-    public static final int ISTORE_1             =  60; // 0x3C
-    public static final int ISTORE_2             =  61; // 0x3D
-    public static final int ISTORE_3             =  62; // 0x3E
-    public static final int LSTORE_0             =  63; // 0x3F
-    public static final int LSTORE_1             =  64; // 0x40
-    public static final int LSTORE_2             =  65; // 0x41
-    public static final int LSTORE_3             =  66; // 0x42
-    public static final int FSTORE_0             =  67; // 0x43
-    public static final int FSTORE_1             =  68; // 0x44
-    public static final int FSTORE_2             =  69; // 0x45
-    public static final int FSTORE_3             =  70; // 0x46
-    public static final int DSTORE_0             =  71; // 0x47
-    public static final int DSTORE_1             =  72; // 0x48
-    public static final int DSTORE_2             =  73; // 0x49
-    public static final int DSTORE_3             =  74; // 0x4A
-    public static final int ASTORE_0             =  75; // 0x4B
-    public static final int ASTORE_1             =  76; // 0x4C
-    public static final int ASTORE_2             =  77; // 0x4D
-    public static final int ASTORE_3             =  78; // 0x4E
-    public static final int IASTORE              =  79; // 0x4F
-    public static final int LASTORE              =  80; // 0x50
-    public static final int FASTORE              =  81; // 0x51
-    public static final int DASTORE              =  82; // 0x52
-    public static final int AASTORE              =  83; // 0x53
-    public static final int BASTORE              =  84; // 0x54
-    public static final int CASTORE              =  85; // 0x55
-    public static final int SASTORE              =  86; // 0x56
-    public static final int POP                  =  87; // 0x57
-    public static final int POP2                 =  88; // 0x58
-    public static final int DUP                  =  89; // 0x59
-    public static final int DUP_X1               =  90; // 0x5A
-    public static final int DUP_X2               =  91; // 0x5B
-    public static final int DUP2                 =  92; // 0x5C
-    public static final int DUP2_X1              =  93; // 0x5D
-    public static final int DUP2_X2              =  94; // 0x5E
-    public static final int SWAP                 =  95; // 0x5F
-    public static final int IADD                 =  96; // 0x60
-    public static final int LADD                 =  97; // 0x61
-    public static final int FADD                 =  98; // 0x62
-    public static final int DADD                 =  99; // 0x63
-    public static final int ISUB                 = 100; // 0x64
-    public static final int LSUB                 = 101; // 0x65
-    public static final int FSUB                 = 102; // 0x66
-    public static final int DSUB                 = 103; // 0x67
-    public static final int IMUL                 = 104; // 0x68
-    public static final int LMUL                 = 105; // 0x69
-    public static final int FMUL                 = 106; // 0x6A
-    public static final int DMUL                 = 107; // 0x6B
-    public static final int IDIV                 = 108; // 0x6C
-    public static final int LDIV                 = 109; // 0x6D
-    public static final int FDIV                 = 110; // 0x6E
-    public static final int DDIV                 = 111; // 0x6F
-    public static final int IREM                 = 112; // 0x70
-    public static final int LREM                 = 113; // 0x71
-    public static final int FREM                 = 114; // 0x72
-    public static final int DREM                 = 115; // 0x73
-    public static final int INEG                 = 116; // 0x74
-    public static final int LNEG                 = 117; // 0x75
-    public static final int FNEG                 = 118; // 0x76
-    public static final int DNEG                 = 119; // 0x77
-    public static final int ISHL                 = 120; // 0x78
-    public static final int LSHL                 = 121; // 0x79
-    public static final int ISHR                 = 122; // 0x7A
-    public static final int LSHR                 = 123; // 0x7B
-    public static final int IUSHR                = 124; // 0x7C
-    public static final int LUSHR                = 125; // 0x7D
-    public static final int IAND                 = 126; // 0x7E
-    public static final int LAND                 = 127; // 0x7F
-    public static final int IOR                  = 128; // 0x80
-    public static final int LOR                  = 129; // 0x81
-    public static final int IXOR                 = 130; // 0x82
-    public static final int LXOR                 = 131; // 0x83
-    public static final int IINC                 = 132; // 0x84
-    public static final int I2L                  = 133; // 0x85
-    public static final int I2F                  = 134; // 0x86
-    public static final int I2D                  = 135; // 0x87
-    public static final int L2I                  = 136; // 0x88
-    public static final int L2F                  = 137; // 0x89
-    public static final int L2D                  = 138; // 0x8A
-    public static final int F2I                  = 139; // 0x8B
-    public static final int F2L                  = 140; // 0x8C
-    public static final int F2D                  = 141; // 0x8D
-    public static final int D2I                  = 142; // 0x8E
-    public static final int D2L                  = 143; // 0x8F
-    public static final int D2F                  = 144; // 0x90
-    public static final int I2B                  = 145; // 0x91
-    public static final int I2C                  = 146; // 0x92
-    public static final int I2S                  = 147; // 0x93
-    public static final int LCMP                 = 148; // 0x94
-    public static final int FCMPL                = 149; // 0x95
-    public static final int FCMPG                = 150; // 0x96
-    public static final int DCMPL                = 151; // 0x97
-    public static final int DCMPG                = 152; // 0x98
-    public static final int IFEQ                 = 153; // 0x99
-    public static final int IFNE                 = 154; // 0x9A
-    public static final int IFLT                 = 155; // 0x9B
-    public static final int IFGE                 = 156; // 0x9C
-    public static final int IFGT                 = 157; // 0x9D
-    public static final int IFLE                 = 158; // 0x9E
-    public static final int IF_ICMPEQ            = 159; // 0x9F
-    public static final int IF_ICMPNE            = 160; // 0xA0
-    public static final int IF_ICMPLT            = 161; // 0xA1
-    public static final int IF_ICMPGE            = 162; // 0xA2
-    public static final int IF_ICMPGT            = 163; // 0xA3
-    public static final int IF_ICMPLE            = 164; // 0xA4
-    public static final int IF_ACMPEQ            = 165; // 0xA5
-    public static final int IF_ACMPNE            = 166; // 0xA6
-    public static final int GOTO                 = 167; // 0xA7
-    public static final int JSR                  = 168; // 0xA8
-    public static final int RET                  = 169; // 0xA9
-    public static final int TABLESWITCH          = 170; // 0xAA
-    public static final int LOOKUPSWITCH         = 171; // 0xAB
-    public static final int IRETURN              = 172; // 0xAC
-    public static final int LRETURN              = 173; // 0xAD
-    public static final int FRETURN              = 174; // 0xAE
-    public static final int DRETURN              = 175; // 0xAF
-    public static final int ARETURN              = 176; // 0xB0
-    public static final int RETURN               = 177; // 0xB1
-    public static final int GETSTATIC            = 178; // 0xB2
-    public static final int PUTSTATIC            = 179; // 0xB3
-    public static final int GETFIELD             = 180; // 0xB4
-    public static final int PUTFIELD             = 181; // 0xB5
-    public static final int INVOKEVIRTUAL        = 182; // 0xB6
-    public static final int INVOKESPECIAL        = 183; // 0xB7
-    public static final int INVOKESTATIC         = 184; // 0xB8
-    public static final int INVOKEINTERFACE      = 185; // 0xB9
-    public static final int XXXUNUSEDXXX         = 186; // 0xBA
-    public static final int NEW                  = 187; // 0xBB
-    public static final int NEWARRAY             = 188; // 0xBC
-    public static final int ANEWARRAY            = 189; // 0xBD
-    public static final int ARRAYLENGTH          = 190; // 0xBE
-    public static final int ATHROW               = 191; // 0xBF
-    public static final int CHECKCAST            = 192; // 0xC0
-    public static final int INSTANCEOF           = 193; // 0xC1
-    public static final int MONITORENTER         = 194; // 0xC2
-    public static final int MONITOREXIT          = 195; // 0xC3
-    public static final int WIDE                 = 196; // 0xC4
-    public static final int MULTIANEWARRAY       = 197; // 0xC5
-    public static final int IFNULL               = 198; // 0xC6
-    public static final int IFNONNULL            = 199; // 0xC7
-    public static final int GOTO_W               = 200; // 0xC8
-    public static final int JSR_W                = 201; // 0xC9
-    public static final int BREAKPOINT           = 202; // 0xCA
-
-    public static final int ILLEGAL = 255;
-    public static final int END = 256;
-
-    /**
-     * The last opcode defined by the JVM specification. To iterate over all JVM bytecodes:
-     * <pre>
-     *     for (int opcode = 0; opcode <= Bytecodes.LAST_JVM_OPCODE; ++opcode) {
-     *         //
-     *     }
-     * </pre>
-     */
-    public static final int LAST_JVM_OPCODE = JSR_W;
-
-    /**
-     * A collection of flags describing various bytecode attributes.
-     */
-    static class Flags {
-
-        /**
-         * Denotes an instruction that ends a basic block and does not let control flow fall through to its lexical successor.
-         */
-        static final int STOP = 0x00000001;
-
-        /**
-         * Denotes an instruction that ends a basic block and may let control flow fall through to its lexical successor.
-         * In practice this means it is a conditional branch.
-         */
-        static final int FALL_THROUGH = 0x00000002;
-
-        /**
-         * Denotes an instruction that has a 2 or 4 byte operand that is an offset to another instruction in the same method.
-         * This does not include the {@link Bytecodes#TABLESWITCH} or {@link Bytecodes#LOOKUPSWITCH} instructions.
-         */
-        static final int BRANCH = 0x00000004;
-
-        /**
-         * Denotes an instruction that reads the value of a static or instance field.
-         */
-        static final int FIELD_READ = 0x00000008;
-
-        /**
-         * Denotes an instruction that writes the value of a static or instance field.
-         */
-        static final int FIELD_WRITE = 0x00000010;
-
-        /**
-         * Denotes an instruction that is not defined in the JVM specification.
-         */
-        static final int EXTENSION = 0x00000020;
-
-        /**
-         * Denotes an instruction that can cause a trap.
-         */
-        static final int TRAP        = 0x00000080;
-        /**
-         * Denotes an instruction that is commutative.
-         */
-        static final int COMMUTATIVE = 0x00000100;
-        /**
-         * Denotes an instruction that is associative.
-         */
-        static final int ASSOCIATIVE = 0x00000200;
-        /**
-         * Denotes an instruction that loads an operand.
-         */
-        static final int LOAD        = 0x00000400;
-        /**
-         * Denotes an instruction that stores an operand.
-         */
-        static final int STORE       = 0x00000800;
-        /**
-         * Denotes the 4 INVOKE* instructions.
-         */
-        static final int INVOKE       = 0x00001000;
-    }
-
-    // Performs a sanity check that none of the flags overlap.
-    static {
-        int allFlags = 0;
-        try {
-            for (Field field : Flags.class.getDeclaredFields()) {
-                int flagsFilter = Modifier.FINAL | Modifier.STATIC;
-                if ((field.getModifiers() & flagsFilter) == flagsFilter && !field.isSynthetic()) {
-                    assert field.getType() == int.class : "Field is not int : " + field;
-                    final int flag = field.getInt(null);
-                    assert flag != 0;
-                    assert (flag & allFlags) == 0 : field.getName() + " has a value conflicting with another flag";
-                    allFlags |= flag;
-                }
-            }
-        } catch (Exception e) {
-            throw new InternalError(e.toString());
-        }
-    }
-
-    /**
-     * An array that maps from a bytecode value to a {@link String} for the corresponding instruction mnemonic.
-     * This will include the root instruction for the three-byte extended instructions.
-     */
-    private static final String[] nameArray = new String[256];
-
-    /**
-     * An array that maps from a bytecode value to the set of {@link Flags} for the corresponding instruction.
-     */
-    private static final int[] flagsArray = new int[256];
-
-    /**
-     * An array that maps from a bytecode value to the length in bytes for the corresponding instruction.
-     */
-    private static final int[] lengthArray = new int[256];
-
-    /**
-     * An array that maps from a bytecode value to the estimated complexity of the bytecode in terms of generated machine code.
-     */
-    private static final int[] compilationComplexityArray = new int[256];
-
-    // Checkstyle: stop
-    static {
-        def(NOP                 , "nop"             , "b"    , 0);
-        def(ACONST_NULL         , "aconst_null"     , "b"    , 0);
-        def(ICONST_M1           , "iconst_m1"       , "b"    , 0);
-        def(ICONST_0            , "iconst_0"        , "b"    , 0);
-        def(ICONST_1            , "iconst_1"        , "b"    , 0);
-        def(ICONST_2            , "iconst_2"        , "b"    , 0);
-        def(ICONST_3            , "iconst_3"        , "b"    , 0);
-        def(ICONST_4            , "iconst_4"        , "b"    , 0);
-        def(ICONST_5            , "iconst_5"        , "b"    , 0);
-        def(LCONST_0            , "lconst_0"        , "b"    , 0);
-        def(LCONST_1            , "lconst_1"        , "b"    , 0);
-        def(FCONST_0            , "fconst_0"        , "b"    , 0);
-        def(FCONST_1            , "fconst_1"        , "b"    , 0);
-        def(FCONST_2            , "fconst_2"        , "b"    , 0);
-        def(DCONST_0            , "dconst_0"        , "b"    , 0);
-        def(DCONST_1            , "dconst_1"        , "b"    , 0);
-        def(BIPUSH              , "bipush"          , "bc"   , 0);
-        def(SIPUSH              , "sipush"          , "bcc"  , 0);
-        def(LDC                 , "ldc"             , "bi"   , 0, TRAP);
-        def(LDC_W               , "ldc_w"           , "bii"  , 0, TRAP);
-        def(LDC2_W              , "ldc2_w"          , "bii"  , 0, TRAP);
-        def(ILOAD               , "iload"           , "bi"   , 0, LOAD);
-        def(LLOAD               , "lload"           , "bi"   , 0, LOAD);
-        def(FLOAD               , "fload"           , "bi"   , 0, LOAD);
-        def(DLOAD               , "dload"           , "bi"   , 0, LOAD);
-        def(ALOAD               , "aload"           , "bi"   , 0, LOAD);
-        def(ILOAD_0             , "iload_0"         , "b"    , 0, LOAD);
-        def(ILOAD_1             , "iload_1"         , "b"    , 0, LOAD);
-        def(ILOAD_2             , "iload_2"         , "b"    , 0, LOAD);
-        def(ILOAD_3             , "iload_3"         , "b"    , 0, LOAD);
-        def(LLOAD_0             , "lload_0"         , "b"    , 0, LOAD);
-        def(LLOAD_1             , "lload_1"         , "b"    , 0, LOAD);
-        def(LLOAD_2             , "lload_2"         , "b"    , 0, LOAD);
-        def(LLOAD_3             , "lload_3"         , "b"    , 0, LOAD);
-        def(FLOAD_0             , "fload_0"         , "b"    , 0, LOAD);
-        def(FLOAD_1             , "fload_1"         , "b"    , 0, LOAD);
-        def(FLOAD_2             , "fload_2"         , "b"    , 0, LOAD);
-        def(FLOAD_3             , "fload_3"         , "b"    , 0, LOAD);
-        def(DLOAD_0             , "dload_0"         , "b"    , 0, LOAD);
-        def(DLOAD_1             , "dload_1"         , "b"    , 0, LOAD);
-        def(DLOAD_2             , "dload_2"         , "b"    , 0, LOAD);
-        def(DLOAD_3             , "dload_3"         , "b"    , 0, LOAD);
-        def(ALOAD_0             , "aload_0"         , "b"    , 0, LOAD);
-        def(ALOAD_1             , "aload_1"         , "b"    , 0, LOAD);
-        def(ALOAD_2             , "aload_2"         , "b"    , 0, LOAD);
-        def(ALOAD_3             , "aload_3"         , "b"    , 0, LOAD);
-        def(IALOAD              , "iaload"          , "b"    , 0, TRAP);
-        def(LALOAD              , "laload"          , "b"    , 0, TRAP);
-        def(FALOAD              , "faload"          , "b"    , 0, TRAP);
-        def(DALOAD              , "daload"          , "b"    , 0, TRAP);
-        def(AALOAD              , "aaload"          , "b"    , 0, TRAP);
-        def(BALOAD              , "baload"          , "b"    , 0, TRAP);
-        def(CALOAD              , "caload"          , "b"    , 0, TRAP);
-        def(SALOAD              , "saload"          , "b"    , 0, TRAP);
-        def(ISTORE              , "istore"          , "bi"   , 0, STORE);
-        def(LSTORE              , "lstore"          , "bi"   , 0, STORE);
-        def(FSTORE              , "fstore"          , "bi"   , 0, STORE);
-        def(DSTORE              , "dstore"          , "bi"   , 0, STORE);
-        def(ASTORE              , "astore"          , "bi"   , 0, STORE);
-        def(ISTORE_0            , "istore_0"        , "b"    , 0, STORE);
-        def(ISTORE_1            , "istore_1"        , "b"    , 0, STORE);
-        def(ISTORE_2            , "istore_2"        , "b"    , 0, STORE);
-        def(ISTORE_3            , "istore_3"        , "b"    , 0, STORE);
-        def(LSTORE_0            , "lstore_0"        , "b"    , 0, STORE);
-        def(LSTORE_1            , "lstore_1"        , "b"    , 0, STORE);
-        def(LSTORE_2            , "lstore_2"        , "b"    , 0, STORE);
-        def(LSTORE_3            , "lstore_3"        , "b"    , 0, STORE);
-        def(FSTORE_0            , "fstore_0"        , "b"    , 0, STORE);
-        def(FSTORE_1            , "fstore_1"        , "b"    , 0, STORE);
-        def(FSTORE_2            , "fstore_2"        , "b"    , 0, STORE);
-        def(FSTORE_3            , "fstore_3"        , "b"    , 0, STORE);
-        def(DSTORE_0            , "dstore_0"        , "b"    , 0, STORE);
-        def(DSTORE_1            , "dstore_1"        , "b"    , 0, STORE);
-        def(DSTORE_2            , "dstore_2"        , "b"    , 0, STORE);
-        def(DSTORE_3            , "dstore_3"        , "b"    , 0, STORE);
-        def(ASTORE_0            , "astore_0"        , "b"    , 0, STORE);
-        def(ASTORE_1            , "astore_1"        , "b"    , 0, STORE);
-        def(ASTORE_2            , "astore_2"        , "b"    , 0, STORE);
-        def(ASTORE_3            , "astore_3"        , "b"    , 0, STORE);
-        def(IASTORE             , "iastore"         , "b"    , 3, TRAP);
-        def(LASTORE             , "lastore"         , "b"    , 3, TRAP);
-        def(FASTORE             , "fastore"         , "b"    , 3, TRAP);
-        def(DASTORE             , "dastore"         , "b"    , 3, TRAP);
-        def(AASTORE             , "aastore"         , "b"    , 4, TRAP);
-        def(BASTORE             , "bastore"         , "b"    , 3, TRAP);
-        def(CASTORE             , "castore"         , "b"    , 3, TRAP);
-        def(SASTORE             , "sastore"         , "b"    , 3, TRAP);
-        def(POP                 , "pop"             , "b"    , 0);
-        def(POP2                , "pop2"            , "b"    , 0);
-        def(DUP                 , "dup"             , "b"    , 0);
-        def(DUP_X1              , "dup_x1"          , "b"    , 0);
-        def(DUP_X2              , "dup_x2"          , "b"    , 0);
-        def(DUP2                , "dup2"            , "b"    , 0);
-        def(DUP2_X1             , "dup2_x1"         , "b"    , 0);
-        def(DUP2_X2             , "dup2_x2"         , "b"    , 0);
-        def(SWAP                , "swap"            , "b"    , 0);
-        def(IADD                , "iadd"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(LADD                , "ladd"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(FADD                , "fadd"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(DADD                , "dadd"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(ISUB                , "isub"            , "b"    , 1);
-        def(LSUB                , "lsub"            , "b"    , 1);
-        def(FSUB                , "fsub"            , "b"    , 1);
-        def(DSUB                , "dsub"            , "b"    , 1);
-        def(IMUL                , "imul"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(LMUL                , "lmul"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(FMUL                , "fmul"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(DMUL                , "dmul"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(IDIV                , "idiv"            , "b"    , 1, TRAP);
-        def(LDIV                , "ldiv"            , "b"    , 1, TRAP);
-        def(FDIV                , "fdiv"            , "b"    , 1);
-        def(DDIV                , "ddiv"            , "b"    , 1);
-        def(IREM                , "irem"            , "b"    , 1, TRAP);
-        def(LREM                , "lrem"            , "b"    , 1, TRAP);
-        def(FREM                , "frem"            , "b"    , 1);
-        def(DREM                , "drem"            , "b"    , 1);
-        def(INEG                , "ineg"            , "b"    , 1);
-        def(LNEG                , "lneg"            , "b"    , 1);
-        def(FNEG                , "fneg"            , "b"    , 1);
-        def(DNEG                , "dneg"            , "b"    , 1);
-        def(ISHL                , "ishl"            , "b"    , 1);
-        def(LSHL                , "lshl"            , "b"    , 1);
-        def(ISHR                , "ishr"            , "b"    , 1);
-        def(LSHR                , "lshr"            , "b"    , 1);
-        def(IUSHR               , "iushr"           , "b"    , 1);
-        def(LUSHR               , "lushr"           , "b"    , 1);
-        def(IAND                , "iand"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(LAND                , "land"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(IOR                 , "ior"             , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(LOR                 , "lor"             , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(IXOR                , "ixor"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(LXOR                , "lxor"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
-        def(IINC                , "iinc"            , "bic"  , 1, LOAD | STORE);
-        def(I2L                 , "i2l"             , "b"    , 1);
-        def(I2F                 , "i2f"             , "b"    , 1);
-        def(I2D                 , "i2d"             , "b"    , 1);
-        def(L2I                 , "l2i"             , "b"    , 1);
-        def(L2F                 , "l2f"             , "b"    , 1);
-        def(L2D                 , "l2d"             , "b"    , 1);
-        def(F2I                 , "f2i"             , "b"    , 1);
-        def(F2L                 , "f2l"             , "b"    , 1);
-        def(F2D                 , "f2d"             , "b"    , 1);
-        def(D2I                 , "d2i"             , "b"    , 1);
-        def(D2L                 , "d2l"             , "b"    , 1);
-        def(D2F                 , "d2f"             , "b"    , 1);
-        def(I2B                 , "i2b"             , "b"    , 1);
-        def(I2C                 , "i2c"             , "b"    , 1);
-        def(I2S                 , "i2s"             , "b"    , 1);
-        def(LCMP                , "lcmp"            , "b"    , 1);
-        def(FCMPL               , "fcmpl"           , "b"    , 1);
-        def(FCMPG               , "fcmpg"           , "b"    , 1);
-        def(DCMPL               , "dcmpl"           , "b"    , 1);
-        def(DCMPG               , "dcmpg"           , "b"    , 1);
-        def(IFEQ                , "ifeq"            , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(IFNE                , "ifne"            , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(IFLT                , "iflt"            , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(IFGE                , "ifge"            , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(IFGT                , "ifgt"            , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(IFLE                , "ifle"            , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(IF_ICMPEQ           , "if_icmpeq"       , "boo"  , 2, COMMUTATIVE | FALL_THROUGH | BRANCH);
-        def(IF_ICMPNE           , "if_icmpne"       , "boo"  , 2, COMMUTATIVE | FALL_THROUGH | BRANCH);
-        def(IF_ICMPLT           , "if_icmplt"       , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(IF_ICMPGE           , "if_icmpge"       , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(IF_ICMPGT           , "if_icmpgt"       , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(IF_ICMPLE           , "if_icmple"       , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(IF_ACMPEQ           , "if_acmpeq"       , "boo"  , 2, COMMUTATIVE | FALL_THROUGH | BRANCH);
-        def(IF_ACMPNE           , "if_acmpne"       , "boo"  , 2, COMMUTATIVE | FALL_THROUGH | BRANCH);
-        def(GOTO                , "goto"            , "boo"  , 1, STOP | BRANCH);
-        def(JSR                 , "jsr"             , "boo"  , 0, STOP | BRANCH);
-        def(RET                 , "ret"             , "bi"   , 0, STOP);
-        def(TABLESWITCH         , "tableswitch"     , ""     , 4, STOP);
-        def(LOOKUPSWITCH        , "lookupswitch"    , ""     , 4, STOP);
-        def(IRETURN             , "ireturn"         , "b"    , 1, TRAP | STOP);
-        def(LRETURN             , "lreturn"         , "b"    , 1, TRAP | STOP);
-        def(FRETURN             , "freturn"         , "b"    , 1, TRAP | STOP);
-        def(DRETURN             , "dreturn"         , "b"    , 1, TRAP | STOP);
-        def(ARETURN             , "areturn"         , "b"    , 1, TRAP | STOP);
-        def(RETURN              , "return"          , "b"    , 1, TRAP | STOP);
-        def(GETSTATIC           , "getstatic"       , "bjj"  , 2, TRAP | FIELD_READ);
-        def(PUTSTATIC           , "putstatic"       , "bjj"  , 2, TRAP | FIELD_WRITE);
-        def(GETFIELD            , "getfield"        , "bjj"  , 2, TRAP | FIELD_READ);
-        def(PUTFIELD            , "putfield"        , "bjj"  , 2, TRAP | FIELD_WRITE);
-        def(INVOKEVIRTUAL       , "invokevirtual"   , "bjj"  , 7, TRAP | INVOKE);
-        def(INVOKESPECIAL       , "invokespecial"   , "bjj"  , 5, TRAP | INVOKE);
-        def(INVOKESTATIC        , "invokestatic"    , "bjj"  , 5, TRAP | INVOKE);
-        def(INVOKEINTERFACE     , "invokeinterface" , "bjja_", 7, TRAP | INVOKE);
-        def(XXXUNUSEDXXX        , "xxxunusedxxx"    , ""     , 0);
-        def(NEW                 , "new"             , "bii"  , 6, TRAP);
-        def(NEWARRAY            , "newarray"        , "bc"   , 6, TRAP);
-        def(ANEWARRAY           , "anewarray"       , "bii"  , 6, TRAP);
-        def(ARRAYLENGTH         , "arraylength"     , "b"    , 2, TRAP);
-        def(ATHROW              , "athrow"          , "b"    , 5, TRAP | STOP);
-        def(CHECKCAST           , "checkcast"       , "bii"  , 3, TRAP);
-        def(INSTANCEOF          , "instanceof"      , "bii"  , 4, TRAP);
-        def(MONITORENTER        , "monitorenter"    , "b"    , 5, TRAP);
-        def(MONITOREXIT         , "monitorexit"     , "b"    , 5, TRAP);
-        def(WIDE                , "wide"            , ""     , 0);
-        def(MULTIANEWARRAY      , "multianewarray"  , "biic" , 6, TRAP);
-        def(IFNULL              , "ifnull"          , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(IFNONNULL           , "ifnonnull"       , "boo"  , 2, FALL_THROUGH | BRANCH);
-        def(GOTO_W              , "goto_w"          , "boooo", 1, STOP | BRANCH);
-        def(JSR_W               , "jsr_w"           , "boooo", 0, STOP | BRANCH);
-        def(BREAKPOINT          , "breakpoint"      , "b"    , 0, TRAP);
-    }
-    // Checkstyle: resume
-
-    /**
-     * Determines if an opcode is commutative.
-     * @param opcode the opcode to check
-     * @return {@code true} iff commutative
-     */
-    public static boolean isCommutative(int opcode) {
-        return (flagsArray[opcode & 0xff] & COMMUTATIVE) != 0;
-    }
-
-    /**
-     * Gets the length of an instruction denoted by a given opcode.
-     *
-     * @param opcode an instruction opcode
-     * @return the length of the instruction denoted by {@code opcode}. If {@code opcode} is an illegal instruction or denotes a
-     *         variable length instruction (e.g. {@link #TABLESWITCH}), then 0 is returned.
-     */
-    public static int lengthOf(int opcode) {
-        return lengthArray[opcode & 0xff];
-    }
-
-    /**
-     * Gets the length of an instruction at a given position in a given bytecode array.
-     * This methods handles variable length and {@linkplain #WIDE widened} instructions.
-     *
-     * @param code an array of bytecode
-     * @param bci the position in {@code code} of an instruction's opcode
-     * @return the length of the instruction at position {@code bci} in {@code code}
-     */
-    public static int lengthOf(byte[] code, int bci) {
-        int opcode = Bytes.beU1(code, bci);
-        int length = Bytecodes.lengthArray[opcode & 0xff];
-        if (length == 0) {
-            switch (opcode) {
-                case TABLESWITCH: {
-                    return new BytecodeTableSwitch(code, bci).size();
-                }
-                case LOOKUPSWITCH: {
-                    return new BytecodeLookupSwitch(code, bci).size();
-                }
-                case WIDE: {
-                    int opc = Bytes.beU1(code, bci + 1);
-                    if (opc == RET) {
-                        return 4;
-                    } else if (opc == IINC) {
-                        return 6;
-                    } else {
-                        return 4; // a load or store bytecode
-                    }
-                }
-                default:
-                    throw new Error("unknown variable-length bytecode: " + opcode);
-            }
-        }
-        return length;
-    }
-
-    /**
-     * Gets the compilation complexity for a given opcode.
-     * @param opcode an opcode
-     * @return a value >= 0
-     */
-    public static int compilationComplexity(int opcode) {
-        return compilationComplexityArray[opcode & 0xff];
-    }
-
-    /**
-     * Gets the lower-case mnemonic for a given opcode.
-     *
-     * @param opcode an opcode
-     * @return the mnemonic for {@code opcode} or {@code "<illegal opcode: " + opcode + ">"} if {@code opcode} is not a legal opcode
-     */
-    public static String nameOf(int opcode) throws IllegalArgumentException {
-        String name = nameArray[opcode & 0xff];
-        if (name == null) {
-            return "<illegal opcode: " + opcode + ">";
-        }
-        return name;
-    }
-
-    /**
-     * Allocation-free version of {@linkplain #nameOf(int)}.
-     * @param opcode an opcode.
-     * @return the mnemonic for {@code opcode} or {@code "<illegal opcode>"} if {@code opcode} is not a legal opcode.
-     */
-    public static String baseNameOf(int opcode) {
-        String name = nameArray[opcode & 0xff];
-        if (name == null) {
-            return "<illegal opcode>";
-        }
-        return name;
-    }
-
-    /**
-     * Gets the opcode corresponding to a given mnemonic.
-     *
-     * @param name an opcode mnemonic
-     * @return the opcode corresponding to {@code mnemonic}
-     * @throws IllegalArgumentException if {@code name} does not denote a valid opcode
-     */
-    public static int valueOf(String name) {
-        for (int opcode = 0; opcode < nameArray.length; ++opcode) {
-            if (name.equalsIgnoreCase(nameArray[opcode])) {
-                return opcode;
-            }
-        }
-        throw new IllegalArgumentException("No opcode for " + name);
-    }
-
-    /**
-     * Determines if a given opcode denotes an instruction that can cause an implicit exception.
-     *
-     * @param opcode an opcode to test
-     * @return {@code true} iff {@code opcode} can cause an implicit exception, {@code false} otherwise
-     */
-    public static boolean canTrap(int opcode) {
-        return (flagsArray[opcode & 0xff] & TRAP) != 0;
-    }
-
-    /**
-     * Determines if a given opcode denotes an instruction that loads a local variable to the operand stack.
-     *
-     * @param opcode an opcode to test
-     * @return {@code true} iff {@code opcode} loads a local variable to the operand stack, {@code false} otherwise
-     */
-    public static boolean isLoad(int opcode) {
-        return (flagsArray[opcode & 0xff] & LOAD) != 0;
-    }
-
-    /**
-     * Determines if a given opcode denotes an instruction that ends a basic block and does not let control flow fall
-     * through to its lexical successor.
-     *
-     * @param opcode an opcode to test
-     * @return {@code true} iff {@code opcode} properly ends a basic block
-     */
-    public static boolean isStop(int opcode) {
-        return (flagsArray[opcode & 0xff] & STOP) != 0;
-    }
-
-    /**
-     * Determines if a given opcode denotes an instruction that stores a value to a local variable
-     * after popping it from the operand stack.
-     *
-     * @param opcode an opcode to test
-     * @return {@code true} iff {@code opcode} stores a value to a local variable, {@code false} otherwise
-     */
-    public static boolean isInvoke(int opcode) {
-        return (flagsArray[opcode & 0xff] & INVOKE) != 0;
-    }
-
-    /**
-     * Determines if a given opcode denotes an instruction that stores a value to a local variable
-     * after popping it from the operand stack.
-     *
-     * @param opcode an opcode to test
-     * @return {@code true} iff {@code opcode} stores a value to a local variable, {@code false} otherwise
-     */
-    public static boolean isStore(int opcode) {
-        return (flagsArray[opcode & 0xff] & STORE) != 0;
-    }
-
-    /**
-     * Determines if a given opcode is an instruction that delimits a basic block.
-     *
-     * @param opcode an opcode to test
-     * @return {@code true} iff {@code opcode} delimits a basic block
-     */
-    public static boolean isBlockEnd(int opcode) {
-        return (flagsArray[opcode & 0xff] & (STOP | FALL_THROUGH)) != 0;
-    }
-
-    /**
-     * Determines if a given opcode is an instruction that has a 2 or 4 byte operand that is an offset to another
-     * instruction in the same method. This does not include the {@linkplain #TABLESWITCH switch} instructions.
-     *
-     * @param opcode an opcode to test
-     * @return {@code true} iff {@code opcode} is a branch instruction with a single operand
-     */
-    public static boolean isBranch(int opcode) {
-        return (flagsArray[opcode & 0xff] & BRANCH) != 0;
-    }
-
-    /**
-     * Determines if a given opcode denotes a conditional branch.
-     * @param opcode
-     * @return {@code true} iff {@code opcode} is a conditional branch
-     */
-    public static boolean isConditionalBranch(int opcode) {
-        return (flagsArray[opcode & 0xff] & FALL_THROUGH) != 0;
-    }
-
-    /**
-     * Determines if a given opcode denotes a standard bytecode. A standard bytecode is
-     * defined in the JVM specification.
-     *
-     * @param opcode an opcode to test
-     * @return {@code true} iff {@code opcode} is a standard bytecode
-     */
-    public static boolean isStandard(int opcode) {
-        return (flagsArray[opcode & 0xff] & EXTENSION) == 0;
-    }
-
-    /**
-     * Determines if a given opcode denotes an extended bytecode.
-     *
-     * @param opcode an opcode to test
-     * @return {@code true} if {@code opcode} is an extended bytecode
-     */
-    public static boolean isExtended(int opcode) {
-        return (flagsArray[opcode & 0xff] & EXTENSION) != 0;
-    }
-
-    /**
-     * Determines if a given opcode is a three-byte extended bytecode.
-     *
-     * @param opcode an opcode to test
-     * @return {@code true} if {@code (opcode & ~0xff) != 0}
-     */
-    public static boolean isThreeByteExtended(int opcode) {
-        return (opcode & ~0xff) != 0;
-    }
-
-    /**
-     * Gets the arithmetic operator name for a given opcode. If {@code opcode} does not denote an
-     * arithmetic instruction, then the {@linkplain #nameOf(int) name} of the opcode is returned
-     * instead.
-     *
-     * @param op an opcode
-     * @return the arithmetic operator name
-     */
-    public static String operator(int op) {
-        // Checkstyle: stop
-        switch (op) {
-            // arithmetic ops
-            case IADD : // fall through
-            case LADD : // fall through
-            case FADD : // fall through
-            case DADD : return "+";
-            case ISUB : // fall through
-            case LSUB : // fall through
-            case FSUB : // fall through
-            case DSUB : return "-";
-            case IMUL : // fall through
-            case LMUL : // fall through
-            case FMUL : // fall through
-            case DMUL : return "*";
-            case IDIV : // fall through
-            case LDIV : // fall through
-            case FDIV : // fall through
-            case DDIV : return "/";
-            case IREM : // fall through
-            case LREM : // fall through
-            case FREM : // fall through
-            case DREM : return "%";
-            // shift ops
-            case ISHL : // fall through
-            case LSHL : return "<<";
-            case ISHR : // fall through
-            case LSHR : return ">>";
-            case IUSHR: // fall through
-            case LUSHR: return ">>>";
-            // logic ops
-            case IAND : // fall through
-            case LAND : return "&";
-            case IOR  : // fall through
-            case LOR  : return "|";
-            case IXOR : // fall through
-            case LXOR : return "^";
-        }
-        // Checkstyle: resume
-        return nameOf(op);
-    }
-
-    /**
-     * Defines a bytecode by entering it into the arrays that record its name, length and flags.
-     *
-     * @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);
-    }
-
-    /**
-     * Defines a bytecode by entering it into the arrays that record its name, length and flags.
-     *
-     * @param name instruction name (lower case)
-     * @param format encodes the length of the instruction
-     * @param flags the set of {@link Flags} associated with the instruction
-     */
-    private static void def(int opcode, String name, String format, int compilationComplexity, int flags) {
-        assert nameArray[opcode] == null : "opcode " + opcode + " is already bound to name " + nameArray[opcode];
-        nameArray[opcode] = name;
-        int instructionLength = format.length();
-        lengthArray[opcode] = instructionLength;
-        compilationComplexityArray[opcode] = compilationComplexity;
-        Bytecodes.flagsArray[opcode] = flags;
-
-        assert !isConditionalBranch(opcode) || isBranch(opcode) : "a conditional branch must also be a branch";
-    }
-
-    /**
-     * Utility for ensuring that the extended opcodes are contiguous and follow on directly
-     * from the standard JVM opcodes. If these conditions do not hold for the input source
-     * file, then it is modified 'in situ' to fix the problem.
-     *
-     * @param args {@code args[0]} is the path to this source file
-     */
-    public static void main(String[] args) throws Exception {
-        Method findWorkspaceDirectory = Class.forName("com.sun.max.ide.JavaProject").getDeclaredMethod("findWorkspaceDirectory");
-        File base = new File((File) findWorkspaceDirectory.invoke(null), "com.oracle.max.cri/src");
-        File file = new File(base, Bytecodes.class.getName().replace('.', File.separatorChar) + ".java").getAbsoluteFile();
-
-        Pattern opcodeDecl = Pattern.compile("(\\s*public static final int )(\\w+)(\\s*=\\s*)(\\d+)(;.*)");
-
-        BufferedReader br = new BufferedReader(new FileReader(file));
-        CharArrayWriter buffer = new CharArrayWriter((int) file.length());
-        PrintWriter out = new PrintWriter(buffer);
-        String line;
-        int lastExtendedOpcode = BREAKPOINT;
-        boolean modified = false;
-        int section = 0;
-        while ((line = br.readLine()) != null) {
-            if (section == 0) {
-                if (line.equals("    // Start extended bytecodes")) {
-                    section = 1;
-                }
-            } else if (section == 1) {
-                if (line.equals("    // End extended bytecodes")) {
-                    section = 2;
-                } else {
-                    Matcher matcher = opcodeDecl.matcher(line);
-                    if (matcher.matches()) {
-                        String name = matcher.group(2);
-                        String value = matcher.group(4);
-                        int opcode = Integer.parseInt(value);
-                        if (nameArray[opcode] == null || !nameArray[opcode].equalsIgnoreCase(name)) {
-                            throw new RuntimeException("Missing definition of name and flags for " + opcode + ":" + name + " -- " + nameArray[opcode]);
-                        }
-                        if (opcode != lastExtendedOpcode + 1) {
-                            System.err.println("Fixed declaration of opcode " + name + " to be " + (lastExtendedOpcode + 1) + " (was " + value + ")");
-                            opcode = lastExtendedOpcode + 1;
-                            line = line.substring(0, matcher.start(4)) + opcode + line.substring(matcher.end(4));
-                            modified = true;
-                        }
-
-                        if (opcode >= 256) {
-                            throw new RuntimeException("Exceeded maximum opcode value with " + name);
-                        }
-
-                        lastExtendedOpcode = opcode;
-                    }
-                }
-            }
-
-            out.println(line);
-        }
-        if (section == 0) {
-            throw new RuntimeException("Did not find line starting extended bytecode declarations:\n\n    // Start extended bytecodes");
-        } else if (section == 1) {
-            throw new RuntimeException("Did not find line ending extended bytecode declarations:\n\n    // End extended bytecodes");
-        }
-
-        if (modified) {
-            out.flush();
-            FileWriter fileWriter = new FileWriter(file);
-            fileWriter.write(buffer.toCharArray());
-            fileWriter.close();
-
-            System.out.println("Modified: " + file);
-        }
-
-
-        // Uncomment to print out visitor method declarations:
-//        for (int opcode = 0; opcode < flags.length; ++opcode) {
-//            if (isExtension(opcode)) {
-//                String visitorParams = length(opcode) == 1 ? "" : "int index";
-//                System.out.println("@Override");
-//                System.out.println("protected void " + name(opcode) + "(" + visitorParams + ") {");
-//                System.out.println("}");
-//                System.out.println();
-//            }
-//        }
-
-        // Uncomment to print out visitor method declarations:
-//        for (int opcode = 0; opcode < flags.length; ++opcode) {
-//            if (isExtension(opcode)) {
-//                System.out.println("case " + name(opcode).toUpperCase() + ": {");
-//                String arg = "";
-//                int length = length(opcode);
-//                if (length == 2) {
-//                    arg = "readUnsigned1()";
-//                } else if (length == 3) {
-//                    arg = "readUnsigned2()";
-//                }
-//                System.out.println("    bytecodeVisitor." + name(opcode) + "(" + arg + ");");
-//                System.out.println("    break;");
-//                System.out.println("}");
-//            }
-//        }
-
-    }
-}
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/Bytes.java	Wed Mar 07 09:50:36 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.java;
-
-/**
- * A collection of utility methods for dealing with bytes, particularly in byte arrays.
- */
-public class Bytes {
-    /**
-     * Gets a signed 1-byte value.
-     * @param data the array containing the data
-     * @param bci the start index of the value to retrieve
-     * @return the signed 1-byte value at index {@code bci} in array {@code data}
-     */
-    public static int beS1(byte[] data, int bci) {
-        return data[bci];
-    }
-
-    /**
-     * Gets a signed 2-byte big-endian value.
-     * @param data the array containing the data
-     * @param bci the start index of the value to retrieve
-     * @return the signed 2-byte, big-endian, value at index {@code bci} in array {@code data}
-     */
-    public static int beS2(byte[] data, int bci) {
-        return (data[bci] << 8) | (data[bci + 1] & 0xff);
-    }
-
-    /**
-     * Gets an unsigned 1-byte value.
-     * @param data the array containing the data
-     * @param bci the start index of the value to retrieve
-     * @return the unsigned 1-byte value at index {@code bci} in array {@code data}
-     */
-    public static int beU1(byte[] data, int bci) {
-        return data[bci] & 0xff;
-    }
-
-    /**
-     * Gets an unsigned 2-byte big-endian value.
-     * @param data the array containing the data
-     * @param bci the start index of the value to retrieve
-     * @return the unsigned 2-byte, big-endian, value at index {@code bci} in array {@code data}
-     */
-    public static int beU2(byte[] data, int bci) {
-        return ((data[bci] & 0xff) << 8) | (data[bci + 1] & 0xff);
-    }
-
-    /**
-     * Gets a signed 4-byte big-endian value.
-     * @param data the array containing the data
-     * @param bci the start index of the value to retrieve
-     * @return the signed 4-byte, big-endian, value at index {@code bci} in array {@code data}
-     */
-    public static int beS4(byte[] data, int bci) {
-        return (data[bci] << 24) | ((data[bci + 1] & 0xff) << 16) | ((data[bci + 2] & 0xff) << 8) | (data[bci + 3] & 0xff);
-    }
-
-    /**
-     * Gets either a signed 2-byte or a signed 4-byte big-endian value.
-     * @param data the array containing the data
-     * @param bci the start index of the value to retrieve
-     * @param fourByte if true, this method will return a 4-byte value
-     * @return the signed 2 or 4-byte, big-endian, value at index {@code bci} in array {@code data}
-     */
-    public static int beSVar(byte[] data, int bci, boolean fourByte) {
-        if (fourByte) {
-            return beS4(data, bci);
-        } else {
-            return beS2(data, bci);
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/FrameStateBuilder.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/FrameStateBuilder.java	Wed Mar 07 10:02:33 2012 -0800
@@ -29,32 +29,29 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.Node.Verbosity;
+import com.oracle.max.graal.graph.iterators.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.PhiNode.PhiType;
-import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
 
-
-public class FrameStateBuilder implements FrameStateAccess {
-
+public class FrameStateBuilder {
+    private final RiResolvedMethod method;
     private final StructuredGraph graph;
 
     private final ValueNode[] locals;
     private final ValueNode[] stack;
-
-    private int stackIndex;
+    private int stackSize;
     private boolean rethrowException;
 
-    private final RiResolvedMethod method;
-
-    public FrameStateBuilder(RiResolvedMethod method, int maxLocals, int maxStackSize, StructuredGraph graph, boolean eagerResolve) {
+    public FrameStateBuilder(RiResolvedMethod method, StructuredGraph graph, boolean eagerResolve) {
         assert graph != null;
         this.method = method;
         this.graph = graph;
-        this.locals = new ValueNode[maxLocals];
+        this.locals = new ValueNode[method.maxLocals()];
         // we always need at least one stack slot (for exceptions)
-        int stackSize = Math.max(1, maxStackSize);
-        this.stack = new ValueNode[stackSize];
+        this.stack = new ValueNode[Math.max(1, method.maxStackSize())];
 
         int javaIndex = 0;
         int index = 0;
@@ -88,33 +85,259 @@
         }
     }
 
-    @Override
-    public String toString() {
-        return String.format("FrameStateBuilder[stackSize=%d]", stackIndex);
+    private FrameStateBuilder(RiResolvedMethod method, StructuredGraph graph, ValueNode[] locals, ValueNode[] stack, int stackSize, boolean rethrowException) {
+        assert locals.length == method.maxLocals();
+        assert stack.length == Math.max(1, method.maxStackSize());
+
+        this.method = method;
+        this.graph = graph;
+        this.locals = locals;
+        this.stack = stack;
+        this.stackSize = stackSize;
+        this.rethrowException = rethrowException;
     }
 
-    public void initializeFrom(FrameState other) {
-        assert locals.length == other.localsSize() : "expected: " + locals.length + ", actual: " + other.localsSize();
-        assert stack.length >= other.stackSize() : "expected: <=" + stack.length + ", actual: " + other.stackSize();
-
-        this.stackIndex = other.stackSize();
-        for (int i = 0; i < other.localsSize(); i++) {
-            locals[i] = other.localAt(i);
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[locals: [");
+        for (int i = 0; i < locals.length; i++) {
+            sb.append(i == 0 ? "" : ",").append(locals[i] == null ? "_" : locals[i].toString(Verbosity.Id));
         }
-        for (int i = 0; i < other.stackSize(); i++) {
-            stack[i] = other.stackAt(i);
+        sb.append("] stack: [");
+        for (int i = 0; i < stackSize; i++) {
+            sb.append(i == 0 ? "" : ",").append(stack[i] == null ? "_" : stack[i].toString(Verbosity.Id));
         }
-        this.rethrowException = other.rethrowException();
+        sb.append("]");
+        if (rethrowException) {
+            sb.append(" rethrowException");
+        }
+        sb.append("]");
+        return sb.toString();
     }
 
     public FrameState create(int bci) {
-        return graph.add(new FrameState(method, bci, locals, stack, stackIndex, rethrowException, false));
+        return graph.add(new FrameState(method, bci, locals, stack, stackSize, rethrowException, false));
+    }
+
+    public FrameState duplicateWithoutStack(int bci) {
+        return graph.add(new FrameState(method, bci, locals, new ValueNode[0], 0, false, false));
+    }
+
+
+    public FrameStateBuilder copy() {
+        return new FrameStateBuilder(method, graph, Arrays.copyOf(locals, locals.length), Arrays.copyOf(stack, stack.length), stackSize, rethrowException);
+    }
+
+    public FrameStateBuilder copyWithException(ValueNode exceptionObject) {
+        ValueNode[] newStack = new ValueNode[stack.length];
+        newStack[0] = exceptionObject;
+        return new FrameStateBuilder(method, graph, Arrays.copyOf(locals, locals.length), newStack, 1, true);
+    }
+
+
+    public boolean isCompatibleWith(FrameStateBuilder other) {
+        assert method == other.method && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method";
+
+        if (stackSize() != other.stackSize()) {
+            return false;
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            ValueNode x = stackAt(i);
+            ValueNode y = other.stackAt(i);
+            if (x != y && ValueUtil.typeMismatch(x, y)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public void merge(MergeNode block, FrameStateBuilder other) {
+        assert isCompatibleWith(other);
+
+        for (int i = 0; i < localsSize(); i++) {
+            storeLocal(i, merge(localAt(i), other.localAt(i), block));
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            storeStack(i, merge(stackAt(i), other.stackAt(i), block));
+        }
+    }
+
+    private ValueNode merge(ValueNode currentValue, ValueNode otherValue, MergeNode block) {
+        if (currentValue == null) {
+            return null;
+
+        } else if (block.isPhiAtMerge(currentValue)) {
+            if (otherValue == null || currentValue.kind() != otherValue.kind()) {
+                deletePhi(currentValue);
+                return null;
+            }
+            ((PhiNode) currentValue).addInput(otherValue);
+            return currentValue;
+
+        } else if (currentValue != otherValue) {
+            assert !(block instanceof LoopBeginNode) : "Phi functions for loop headers are create eagerly for all locals and stack slots";
+            if (otherValue == null || currentValue.kind() != otherValue.kind()) {
+                return null;
+            }
+
+            PhiNode phi = graph.unique(new PhiNode(currentValue.kind(), block, PhiType.Value));
+            for (int i = 0; i < block.phiPredecessorCount(); i++) {
+                phi.addInput(currentValue);
+            }
+            phi.addInput(otherValue);
+            assert phi.valueCount() == block.phiPredecessorCount() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.phiPredecessorCount();
+            return phi;
+
+        } else {
+            return currentValue;
+        }
+    }
+
+    private void deletePhi(Node phi) {
+        if (phi.isDeleted()) {
+            return;
+        }
+        // Collect all phi functions that use this phi so that we can delete them recursively (after we delete ourselfs to avoid circles).
+        List<Node> phiUsages = phi.usages().filter(NodePredicates.isA(PhiNode.class)).snapshot();
+
+        // Remove the phi function from all FrameStates where it is used and then delete it.
+        assert phi.usages().filter(NodePredicates.isNotA(FrameState.class)).filter(NodePredicates.isNotA(PhiNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states";
+        phi.replaceAtUsages(null);
+        phi.safeDelete();
+
+        for (Node phiUsage : phiUsages) {
+            deletePhi(phiUsage);
+        }
+    }
+
+    public void insertLoopPhis(LoopBeginNode loopBegin) {
+        for (int i = 0; i < localsSize(); i++) {
+            storeLocal(i, createLoopPhi(loopBegin, localAt(i)));
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            storeStack(i, createLoopPhi(loopBegin, stackAt(i)));
+        }
     }
 
-    public FrameState duplicateWithException(int bci, ValueNode exceptionObject) {
-        FrameState frameState = graph.add(new FrameState(method, bci, locals, new ValueNode[]{exceptionObject}, 1, true, false));
-        frameState.setOuterFrameState(outerFrameState());
-        return frameState;
+    private PhiNode createLoopPhi(MergeNode block, ValueNode value) {
+        if (value == null) {
+            return null;
+        }
+        assert !block.isPhiAtMerge(value) : "phi function for this block already created";
+
+        PhiNode phi = graph.unique(new PhiNode(value.kind(), block, PhiType.Value));
+        phi.addInput(value);
+        return phi;
+    }
+
+    public void cleanupDeletedPhis() {
+        for (int i = 0; i < localsSize(); i++) {
+            if (localAt(i) != null && localAt(i).isDeleted()) {
+                assert localAt(i) instanceof PhiNode : "Only phi functions can be deleted during parsing";
+                storeLocal(i, null);
+            }
+        }
+    }
+
+    public void clearNonLiveLocals(BitMap liveness) {
+        if (liveness == null) {
+            return;
+        }
+        assert liveness.size() == locals.length;
+        for (int i = 0; i < locals.length; i++) {
+            if (!liveness.get(i)) {
+                locals[i] = null;
+            }
+        }
+    }
+
+    public boolean rethrowException() {
+        return rethrowException;
+    }
+
+    public void setRethrowException(boolean b) {
+        rethrowException = b;
+    }
+
+
+    /**
+     * Returns the size of the local variables.
+     *
+     * @return the size of the local variables
+     */
+    public int localsSize() {
+        return locals.length;
+    }
+
+    /**
+     * Gets the current size (height) of the stack.
+     */
+    public int stackSize() {
+        return stackSize;
+    }
+
+    /**
+     * Gets the value in the local variables at the specified index, without any sanity checking.
+     *
+     * @param i the index into the locals
+     * @return the instruction that produced the value for the specified local
+     */
+    protected final ValueNode localAt(int i) {
+        return locals[i];
+    }
+
+    /**
+     * Get the value on the stack at the specified stack index.
+     *
+     * @param i the index into the stack, with {@code 0} being the bottom of the stack
+     * @return the instruction at the specified position in the stack
+     */
+    protected final ValueNode stackAt(int i) {
+        return stack[i];
+    }
+
+    /**
+     * Loads the local variable at the specified index, checking that the returned value is non-null
+     * and that two-stack values are properly handled.
+     *
+     * @param i the index of the local variable to load
+     * @return the instruction that produced the specified local
+     */
+    public ValueNode loadLocal(int i) {
+        ValueNode x = locals[i];
+        assert !x.isDeleted();
+        assert !isTwoSlot(x.kind()) || locals[i + 1] == null;
+        assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].kind());
+        return x;
+    }
+
+    /**
+     * Stores a given local variable at the specified index. If the value is a {@linkplain CiKind#isDoubleWord() double word},
+     * then the next local variable index is also overwritten.
+     *
+     * @param i the index at which to store
+     * @param x the instruction which produces the value for the local
+     */
+    public void storeLocal(int i, ValueNode x) {
+        assert x == null || x.kind() != CiKind.Void && x.kind() != CiKind.Illegal : "unexpected value: " + x;
+        locals[i] = x;
+        if (x != null && isTwoSlot(x.kind())) {
+            // if this is a double word, then kill i+1
+            locals[i + 1] = null;
+        }
+        if (x != null && i > 0) {
+            ValueNode p = locals[i - 1];
+            if (p != null && isTwoSlot(p.kind())) {
+                // if there was a double word at i - 1, then kill it
+                locals[i - 1] = null;
+            }
+        }
+    }
+
+    private void storeStack(int i, ValueNode x) {
+        assert x == null || stack[i] == null || x.kind() == stack[i].kind() : "Method does not handle changes from one-slot to two-slot values";
+        stack[i] = x;
     }
 
     /**
@@ -123,7 +346,7 @@
      * @param x the instruction to push onto the stack
      */
     public void push(CiKind kind, ValueNode x) {
-        assert kind != CiKind.Void;
+        assert !x.isDeleted() && x.kind() != CiKind.Void && x.kind() != CiKind.Illegal;
         xpush(assertKind(kind, x));
         if (isTwoSlot(kind)) {
             xpush(null);
@@ -135,9 +358,8 @@
      * @param x the instruction to push onto the stack
      */
     public void xpush(ValueNode x) {
-        assert x == null || !x.isDeleted();
-        assert x == null || (x.kind() != CiKind.Void && x.kind() != CiKind.Illegal) : "unexpected value: " + x;
-        stack[stackIndex++] = x;
+        assert x == null || (!x.isDeleted() && x.kind() != CiKind.Void && x.kind() != CiKind.Illegal);
+        stack[stackSize++] = x;
     }
 
     /**
@@ -215,7 +437,7 @@
      * @return x the instruction popped off the stack
      */
     public ValueNode xpop() {
-        ValueNode result = stack[--stackIndex];
+        ValueNode result = stack[--stackSize];
         assert result == null || !result.isDeleted();
         return result;
     }
@@ -276,7 +498,7 @@
      * @return an array containing the arguments off of the stack
      */
     public ValueNode[] popArguments(int slotSize, int argSize) {
-        int base = stackIndex - slotSize;
+        int base = stackSize - slotSize;
         ValueNode[] r = new ValueNode[argSize];
         int argIndex = 0;
         int stackindex = 0;
@@ -286,7 +508,7 @@
             r[argIndex++] = element;
             stackindex += stackSlots(element.kind());
         }
-        stackIndex = base;
+        stackSize = base;
         return r;
     }
 
@@ -309,173 +531,10 @@
     }
 
     /**
-     * Truncates this stack to the specified size.
-     * @param size the size to truncate to
-     */
-    public void truncateStack(int size) {
-        stackIndex = size;
-        assert stackIndex >= 0;
-    }
-
-    /**
      * Clears all values on this stack.
      */
     public void clearStack() {
-        stackIndex = 0;
-    }
-
-    /**
-     * Loads the local variable at the specified index.
-     *
-     * @param i the index of the local variable to load
-     * @return the instruction that produced the specified local
-     */
-    public ValueNode loadLocal(int i) {
-        ValueNode x = locals[i];
-        if (x != null) {
-            if (x instanceof PhiNode) {
-                assert ((PhiNode) x).type() == PhiType.Value;
-                if (x.isDeleted()) {
-                    return null;
-                }
-            }
-            assert !isTwoSlot(x.kind()) || locals[i + 1] == null || locals[i + 1] instanceof PhiNode;
-        }
-        return x;
-    }
-
-    /**
-     * Stores a given local variable at the specified index. If the value is a {@linkplain CiKind#isDoubleWord() double word},
-     * then the next local variable index is also overwritten.
-     *
-     * @param i the index at which to store
-     * @param x the instruction which produces the value for the local
-     */
-    public void storeLocal(int i, ValueNode x) {
-        assert x.kind() != CiKind.Void && x.kind() != CiKind.Illegal : "unexpected value: " + x;
-        locals[i] = x;
-        if (isTwoSlot(x.kind())) {
-            // (tw) if this was a double word then kill i+1
-            locals[i + 1] = null;
-        }
-        if (i > 0) {
-            // if there was a double word at i - 1, then kill it
-            ValueNode p = locals[i - 1];
-            if (p != null && isTwoSlot(p.kind())) {
-                locals[i - 1] = null;
-            }
-        }
-    }
-
-    /**
-     * Get the value on the stack at the specified stack index.
-     *
-     * @param i the index into the stack, with {@code 0} being the bottom of the stack
-     * @return the instruction at the specified position in the stack
-     */
-    public final ValueNode stackAt(int i) {
-        return stack[i];
-    }
-
-    /**
-     * Gets the value in the local variables at the specified index.
-     *
-     * @param i the index into the locals
-     * @return the instruction that produced the value for the specified local
-     */
-    public final ValueNode localAt(int i) {
-        return locals[i];
-    }
-
-    /**
-     * Returns the size of the local variables.
-     *
-     * @return the size of the local variables
-     */
-    public int localsSize() {
-        return locals.length;
-    }
-
-    /**
-     * Gets the current size (height) of the stack.
-     */
-    public int stackSize() {
-        return stackIndex;
-    }
-
-    public Iterator<ValueNode> locals() {
-        return new ValueArrayIterator(locals);
-    }
-
-    public Iterator<ValueNode> stack() {
-        return new ValueArrayIterator(locals);
-    }
-
-
-    private static class ValueArrayIterator implements Iterator<ValueNode> {
-        private final ValueNode[] array;
-        private int index;
-
-        public ValueArrayIterator(ValueNode[] array, int length) {
-            assert length <= array.length;
-            this.array = array;
-            this.index = 0;
-        }
-
-        public ValueArrayIterator(ValueNode[] array) {
-            this(array, array.length);
-        }
-
-        @Override
-        public boolean hasNext() {
-            return index < array.length;
-        }
-
-        @Override
-        public ValueNode next() {
-            return array[index++];
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException("cannot remove from array");
-        }
-
-    }
-
-
-    @Override
-    public FrameState duplicate(int bci) {
-        return create(bci);
-    }
-
-    @Override
-    public ValueNode valueAt(int i) {
-        if (i < locals.length) {
-            return locals[i];
-        } else {
-            return stack[i - locals.length];
-        }
-    }
-
-    @Override
-    public FrameState outerFrameState() {
-        return null;
-    }
-
-    public FrameState duplicateWithoutStack(int bci) {
-        FrameState frameState = graph.add(new FrameState(method, bci, locals, new ValueNode[0], 0, false, false));
-        frameState.setOuterFrameState(outerFrameState());
-        return frameState;
-    }
-
-    @Override
-    public boolean rethrowException() {
-        return rethrowException;
-    }
-
-    public void setRethrowException(boolean b) {
-        rethrowException = b;
+        stackSize = 0;
     }
 
     public static int stackSlots(CiKind kind) {
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Wed Mar 07 10:02:33 2012 -0800
@@ -22,12 +22,13 @@
  */
 package com.oracle.max.graal.java;
 
-import static com.oracle.max.graal.java.Bytecodes.*;
+import static com.oracle.max.graal.java.bytecode.Bytecodes.*;
 import static java.lang.reflect.Modifier.*;
 
 import java.lang.reflect.*;
 import java.util.*;
 
+
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.cri.ri.RiType.Representation;
@@ -38,8 +39,8 @@
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.java.BciBlockMapping.Block;
-import com.oracle.max.graal.java.BciBlockMapping.DeoptBlock;
 import com.oracle.max.graal.java.BciBlockMapping.ExceptionBlock;
+import com.oracle.max.graal.java.bytecode.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction;
 import com.oracle.max.graal.nodes.PhiNode.PhiType;
@@ -47,7 +48,7 @@
 import com.oracle.max.graal.nodes.extended.*;
 import com.oracle.max.graal.nodes.java.*;
 import com.oracle.max.graal.nodes.java.MethodCallTargetNode.InvokeKind;
-import com.oracle.max.graal.nodes.spi.*;
+import com.oracle.max.graal.nodes.type.*;
 
 /**
  * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
@@ -80,30 +81,32 @@
     private FrameStateBuilder frameState;          // the current execution state
     private Block currentBlock;
 
-    private int nextBlockNumber;
-
     private ValueNode methodSynchronizedObject;
     private ExceptionBlock unwindBlock;
     private Block returnBlock;
 
-    // the worklist of blocks, sorted by depth first number
-    private final PriorityQueue<Block> workList = new PriorityQueue<>(10, new Comparator<Block>() {
-        public int compare(Block o1, Block o2) {
-            return o1.blockID - o2.blockID;
-        }
-    });
-
     private FixedWithNextNode lastInstr;                 // the last instruction added
 
-    private Set<Block> blocksOnWorklist;
-    private Set<Block> blocksVisited;
-
     private BitSet canTrapBitSet;
 
     public static final Map<RiMethod, StructuredGraph> cachedGraphs = new WeakHashMap<>();
 
     private final GraphBuilderConfiguration config;
 
+
+    /**
+     * Node that marks the begin of block during bytecode parsing.  When a block is identified the first
+     * time as a jump target, the placeholder is created and used as the successor for the jump.  When the
+     * block is seen the second time, a MergeNode is created to correctly merge the now two different
+     * predecessor states.
+     */
+    private static class BlockPlaceholderNode extends FixedWithNextNode implements Node.IterableNodeType {
+        public BlockPlaceholderNode() {
+            super(StampFactory.illegal());
+        }
+    }
+
+
     public GraphBuilderPhase(RiRuntime runtime) {
         this(runtime, GraphBuilderConfiguration.getDefault());
     }
@@ -121,14 +124,12 @@
         assert method.code() != null : "method must contain bytecodes: " + method;
         this.stream = new BytecodeStream(method.code());
         this.constantPool = method.getConstantPool();
-        this.blocksOnWorklist = new HashSet<>();
-        this.blocksVisited = new HashSet<>();
         unwindBlock = null;
         returnBlock = null;
         methodSynchronizedObject = null;
         exceptionHandlers = null;
         this.currentGraph = graph;
-        this.frameState = new FrameStateBuilder(method, method.maxLocals(), method.maxStackSize(), graph, config.eagerResolving());
+        this.frameState = new FrameStateBuilder(method, graph, config.eagerResolving());
         build();
     }
 
@@ -140,12 +141,8 @@
     private BciBlockMapping createBlockMap() {
         BciBlockMapping map = new BciBlockMapping(method, config.useBranchPrediction());
         map.build();
+        Debug.dump(map, CiUtil.format("After block building %f %R %H.%n(%P)", method));
 
-//        if (currentContext.isObserved()) {
-//            String label = CiUtil.format("BlockListBuilder %f %R %H.%n(%P)", method);
-//            currentContext.observable.fireCompilationEvent(label, map);
-//        }
-        // TODO(tw): Reinstall this logging code when debug framework is finished.
         return map;
     }
 
@@ -165,8 +162,6 @@
 
         exceptionHandlers = blockMap.exceptionHandlers();
 
-        nextBlockNumber = blockMap.blocks.size();
-
         lastInstr = currentGraph.start();
         if (isSynchronized(method.accessFlags())) {
             // add a monitor enter to the start block
@@ -174,6 +169,7 @@
             methodSynchronizedObject = synchronizedObject(frameState, method);
             lastInstr = genMonitorEnter(methodSynchronizedObject);
         }
+        frameState.clearNonLiveLocals(blockMap.startBlock.localsLiveIn);
 
         // finish the start block
         ((AbstractStateSplit) lastInstr).setStateAfter(frameState.create(0));
@@ -181,14 +177,21 @@
             appendGoto(createTarget(blockMap.startBlock, frameState));
         } else {
             blockMap.startBlock.firstInstruction = lastInstr;
+            blockMap.startBlock.entryState = frameState;
         }
-        addToWorkList(blockMap.startBlock);
 
-        iterateAllBlocks();
+        for (Block block : blockMap.blocks) {
+            processBlock(block);
+        }
+        processBlock(returnBlock);
+        processBlock(unwindBlock);
+
+        Debug.dump(currentGraph, "After bytecode parsing");
+
         connectLoopEndToBegin();
 
         // remove Placeholders (except for loop exits)
-        for (PlaceholderNode n : currentGraph.getNodes(PlaceholderNode.class)) {
+        for (BlockPlaceholderNode n : currentGraph.getNodes(BlockPlaceholderNode.class)) {
             currentGraph.removeFixed(n);
         }
 
@@ -204,18 +207,13 @@
         }
     }
 
-    private int nextBlockNumber() {
-        return nextBlockNumber++;
-    }
-
     private Block unwindBlock(int bci) {
         if (unwindBlock == null) {
             unwindBlock = new ExceptionBlock();
             unwindBlock.startBci = -1;
             unwindBlock.endBci = -1;
             unwindBlock.deoptBci = bci;
-            unwindBlock.blockID = nextBlockNumber();
-            addToWorkList(unwindBlock);
+            unwindBlock.blockID = Integer.MAX_VALUE;
         }
         return unwindBlock;
     }
@@ -225,80 +223,11 @@
             returnBlock = new Block();
             returnBlock.startBci = bci;
             returnBlock.endBci = bci;
-            returnBlock.blockID = nextBlockNumber();
-            addToWorkList(returnBlock);
+            returnBlock.blockID = Integer.MAX_VALUE;
         }
         return returnBlock;
     }
 
-    private void markOnWorkList(Block block) {
-        blocksOnWorklist.add(block);
-    }
-
-    private boolean isOnWorkList(Block block) {
-        return blocksOnWorklist.contains(block);
-    }
-
-    private void markVisited(Block block) {
-        blocksVisited.add(block);
-    }
-
-    private boolean isVisited(Block block) {
-        return blocksVisited.contains(block);
-    }
-
-    public void mergeOrClone(Block target, FrameStateAccess newState, StateSplit first) {
-
-        int bci = target.startBci;
-        if (target instanceof ExceptionBlock) {
-            bci = ((ExceptionBlock) target).deoptBci;
-        }
-
-        FrameState existingState = first.stateAfter();
-        if (existingState == null) {
-            // There was no state : new target
-            // copy state because it is modified
-            first.setStateAfter(newState.duplicate(bci));
-            return;
-        } else {
-            if (!GraalOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(newState)) {
-                // stacks or locks do not match--bytecodes would not verify
-                TTY.println(existingState.toString());
-                TTY.println(newState.duplicate(0).toString());
-                throw new CiBailout("stack or locks do not match");
-            }
-            assert existingState.localsSize() == newState.localsSize();
-            assert existingState.stackSize() == newState.stackSize();
-
-            if (first instanceof PlaceholderNode) {
-                // there is no merge yet here
-                PlaceholderNode p = (PlaceholderNode) first;
-                if (p.predecessor() == null) {
-                    //nothing seems to come here, yet there's a state?
-                    Debug.log("Funky control flow going to @bci %d : we already have a state but no predecessor", bci);
-                    p.setStateAfter(newState.duplicate(bci));
-                    return;
-                } else {
-                    //create a merge
-                    MergeNode merge = currentGraph.add(new MergeNode());
-                    FixedNode next = p.next();
-                    if (p.predecessor() != null) {
-                        EndNode end = currentGraph.add(new EndNode());
-                        p.setNext(end);
-                        merge.addForwardEnd(end);
-                    }
-                    merge.setNext(next);
-                    FrameState mergeState = existingState.duplicate(bci);
-                    merge.setStateAfter(mergeState);
-                    mergeState.merge(merge, newState);
-                    target.firstInstruction = merge;
-                }
-            } else {
-                existingState.merge((MergeNode) first, newState);
-            }
-        }
-    }
-
     public BytecodeStream stream() {
         return stream;
     }
@@ -375,9 +304,9 @@
         } else {
             currentExceptionObject = exceptionObject;
         }
-        FrameState stateWithException = frameState.duplicateWithException(bci, currentExceptionObject);
+        FrameStateBuilder stateWithException = frameState.copyWithException(currentExceptionObject);
         if (newObj != null) {
-            newObj.setStateAfter(stateWithException);
+            newObj.setStateAfter(stateWithException.create(bci));
         }
         FixedNode target = createTarget(dispatchBlock, stateWithException);
         if (exceptionObject == null) {
@@ -600,7 +529,7 @@
     private void genIncrement() {
         int index = stream().readLocalIndex();
         int delta = stream().readIncrement();
-        ValueNode x = frameState.localAt(index);
+        ValueNode x = frameState.loadLocal(index);
         ValueNode y = append(ConstantNode.forInt(delta, currentGraph));
         frameState.storeLocal(index, append(currentGraph.unique(new IntegerAddNode(CiKind.Int, x, y))));
     }
@@ -616,23 +545,25 @@
 
     private void ifNode(ValueNode x, Condition cond, ValueNode y) {
         assert !x.isDeleted() && !y.isDeleted();
-        double takenProbability = profilingInfo.getBranchTakenProbability(bci());
-        if (takenProbability < 0) {
-            assert takenProbability == -1 : "invalid probability";
+        assert currentBlock.normalSuccessors == 2 : currentBlock.normalSuccessors;
+        Block trueBlock = currentBlock.successors.get(0);
+        Block falseBlock = currentBlock.successors.get(1);
+        if (trueBlock == falseBlock) {
+            appendGoto(createTarget(trueBlock, frameState));
+            return;
+        }
+
+        double probability = profilingInfo.getBranchTakenProbability(bci());
+        if (probability < 0) {
+            assert probability == -1 : "invalid probability";
             Debug.log("missing probability in %s at bci %d", method, bci());
             takenProbability = 0.5;
         }
 
         CompareNode condition = currentGraph.unique(new CompareNode(x, cond, y));
-        FixedNode trueSuccessor = createTarget(currentBlock.successors.get(0), frameState);
-        FixedNode falseSuccessor = createTarget(currentBlock.successors.get(1), frameState);
-        if (trueSuccessor == falseSuccessor) {
-            appendGoto(trueSuccessor);
-        } else {
-            append(currentGraph.add(new IfNode(condition, trueSuccessor, falseSuccessor, takenProbability)));
-        }
-
-        assert currentBlock.normalSuccessors == 2 : currentBlock.normalSuccessors;
+        BeginNode trueSuccessor = createBlockTarget(probability, trueBlock, frameState);
+        BeginNode falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState);
+        append(currentGraph.add(new IfNode(condition, trueSuccessor, falseSuccessor, probability)));
     }
 
     private void genIfZero(Condition cond) {
@@ -765,7 +696,7 @@
             InstanceOfNode instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, hints, Util.isFinalClass(resolvedType), false);
             frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph)));
         } else {
-            PlaceholderNode trueSucc = currentGraph.add(new PlaceholderNode());
+            BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode());
             DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile));
             IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new NullCheckNode(object, true)), trueSucc, deopt, 1));
             append(ifNode);
@@ -869,8 +800,8 @@
     }
 
     private ExceptionInfo emitNullCheck(ValueNode receiver) {
-        PlaceholderNode trueSucc = currentGraph.add(new PlaceholderNode());
-        PlaceholderNode falseSucc = currentGraph.add(new PlaceholderNode());
+        BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode());
+        BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode());
         IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new NullCheckNode(receiver, false)), trueSucc, falseSucc, 1));
 
         append(ifNode);
@@ -881,15 +812,15 @@
             return new ExceptionInfo(falseSucc, exception);
         } else {
             RuntimeCallNode call = currentGraph.add(new RuntimeCallNode(CiRuntimeCall.CreateNullPointerException));
-            call.setStateAfter(frameState.duplicate(bci()));
+            call.setStateAfter(frameState.create(bci()));
             falseSucc.setNext(call);
             return new ExceptionInfo(call, call);
         }
     }
 
     private ExceptionInfo emitBoundsCheck(ValueNode index, ValueNode length) {
-        PlaceholderNode trueSucc = currentGraph.add(new PlaceholderNode());
-        PlaceholderNode falseSucc = currentGraph.add(new PlaceholderNode());
+        BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode());
+        BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode());
         IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new CompareNode(index, Condition.BT, length)), trueSucc, falseSucc, 1));
 
         append(ifNode);
@@ -900,7 +831,7 @@
             return new ExceptionInfo(falseSucc, exception);
         } else {
             RuntimeCallNode call = currentGraph.add(new RuntimeCallNode(CiRuntimeCall.CreateOutOfBoundsException, new ValueNode[] {index}));
-            call.setStateAfter(frameState.duplicate(bci()));
+            call.setStateAfter(frameState.create(bci()));
             falseSucc.setNext(call);
             return new ExceptionInfo(call, call);
         }
@@ -930,7 +861,7 @@
                     merge.addForwardEnd(end);
                     phi.addInput(info.exception);
                 }
-                merge.setStateAfter(frameState.duplicate(bci()));
+                merge.setStateAfter(frameState.create(bci()));
                 exception = new ExceptionInfo(merge, phi);
             }
 
@@ -938,7 +869,7 @@
             if (entry != null) {
                 exception.exceptionEdge.setNext(entry);
             } else {
-                exception.exceptionEdge.setNext(createTarget(unwindBlock(bci()), frameState.duplicateWithException(bci(), exception.exception)));
+                exception.exceptionEdge.setNext(createTarget(unwindBlock(bci()), frameState.copyWithException(exception.exception)));
             }
             Debug.metric("ExplicitExceptions").increment();
         }
@@ -1106,6 +1037,10 @@
                 result = append(invoke);
                 frameState.pushReturn(resultType, result);
                 Block nextBlock = currentBlock.successors.get(0);
+
+                assert bci() == currentBlock.endBci;
+                frameState.clearNonLiveLocals(currentBlock.localsLiveOut);
+
                 invoke.setNext(createTarget(nextBlock, frameState));
                 invoke.setStateAfter(frameState.create(nextBlock.startBci));
             } else {
@@ -1193,9 +1128,10 @@
         int nofCases = ts.numberOfCases() + 1; // including default case
         assert currentBlock.normalSuccessors == nofCases;
 
-        TableSwitchNode tableSwitch = currentGraph.add(new TableSwitchNode(value, ts.lowKey(), switchProbability(nofCases, bci)));
+        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, BeginNode.begin(createTarget(currentBlock.successors.get(i), frameState)));
+            tableSwitch.setBlockSuccessor(i, createBlockTarget(probabilities[i], currentBlock.successors.get(i), frameState));
         }
         append(tableSwitch);
     }
@@ -1226,9 +1162,10 @@
         for (int i = 0; i < nofCases - 1; ++i) {
             keys[i] = ls.keyAt(i);
         }
-        LookupSwitchNode lookupSwitch = currentGraph.add(new LookupSwitchNode(value, keys, switchProbability(nofCases, bci)));
+        double[] probabilities = switchProbability(nofCases, bci);
+        LookupSwitchNode lookupSwitch = currentGraph.add(new LookupSwitchNode(value, keys, probabilities));
         for (int i = 0; i < nofCases; ++i) {
-            lookupSwitch.setBlockSuccessor(i, BeginNode.begin(createTarget(currentBlock.successors.get(i), frameState)));
+            lookupSwitch.setBlockSuccessor(i, createBlockTarget(probabilities[i], currentBlock.successors.get(i), frameState));
         }
         append(lookupSwitch);
     }
@@ -1259,134 +1196,170 @@
         return x;
     }
 
-    private FixedNode createTarget(Block block, FrameStateAccess stateAfter) {
+    private FixedNode createTarget(Block block, FrameStateBuilder stateAfter) {
         assert block != null && stateAfter != null;
-        assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null :
-            "non-loop block must be iterated after all its predecessors. startBci=" + block.startBci + ", " + block.getClass().getSimpleName() + ", " + block.firstInstruction.next();
-
-        if (block.isExceptionEntry) {
-            assert stateAfter.stackSize() == 1;
-        }
+        assert !block.isExceptionEntry || stateAfter.stackSize() == 1;
 
         if (block.firstInstruction == null) {
-            if (block.isLoopHeader) {
-                LoopBeginNode loop = currentGraph.add(new LoopBeginNode());
-                EndNode end = currentGraph.add(new EndNode());
-                loop.addForwardEnd(end);
-                PlaceholderNode p = currentGraph.add(new PlaceholderNode());
-                p.setNext(end);
-                block.firstInstruction = p;
-            } else {
-                block.firstInstruction = currentGraph.add(new PlaceholderNode());
-            }
+            // This is the first time we see this block as a branch target.
+            // Create and return a placeholder that later can be replaced with a MergeNode when we see this block again.
+            block.firstInstruction = currentGraph.add(new BlockPlaceholderNode());
+            block.entryState = stateAfter.copy();
+            block.entryState.clearNonLiveLocals(block.localsLiveIn);
+
+            Debug.log("createTarget %s: first visit, result: %s", block, block.firstInstruction);
+            return block.firstInstruction;
         }
-        LoopEndNode loopend = null;
-        StateSplit mergeAt = null;
-        if (block.isLoopHeader && isVisited(block)) { // backedge
-            loopend = currentGraph.add(new LoopEndNode(loopBegin(block)));
-            mergeAt = loopBegin(block);
-        } else {
-            mergeAt = (StateSplit) block.firstInstruction;
+
+        // We already saw this block before, so we have to merge states.
+        if (!block.entryState.isCompatibleWith(stateAfter)) {
+            throw new CiBailout("stacks do not match; bytecodes would not verify");
         }
 
-        mergeOrClone(block, stateAfter, mergeAt);
-        addToWorkList(block);
+        if (block.firstInstruction instanceof LoopBeginNode) {
+            assert block.isLoopHeader && currentBlock.blockID >= block.blockID : "must be backward branch";
+            // Backward loop edge. We need to create a special LoopEndNode and merge with the loop begin node created before.
+            LoopBeginNode loopBegin = (LoopBeginNode) block.firstInstruction;
+            LoopEndNode result = currentGraph.add(new LoopEndNode(loopBegin));
+            block.entryState.merge(loopBegin, stateAfter);
+
+            Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
+            return result;
+        }
+        assert currentBlock == null || currentBlock.blockID < block.blockID : "must not be backward branch";
+        assert block.firstInstruction.next() == null : "bytecodes already parsed for block";
 
-        FixedNode result = null;
-        if (loopend != null) {
-            result = loopend;
-        } else {
-            result = block.firstInstruction;
+        if (block.firstInstruction instanceof BlockPlaceholderNode) {
+            // This is the second time we see this block. Create the actual MergeNode and the End Node for the already existing edge.
+            // For simplicity, we leave the placeholder in the graph and just append the new nodes after the placeholder.
+            BlockPlaceholderNode placeholder = (BlockPlaceholderNode) block.firstInstruction;
+
+            // The EndNode for the already existing edge.
+            EndNode end = currentGraph.add(new EndNode());
+            // The MergeNode that replaces the placeholder.
+            MergeNode mergeNode  = currentGraph.add(new MergeNode());
+            FixedNode next = placeholder.next();
+
+            placeholder.setNext(end);
+            mergeNode.addForwardEnd(end);
+            mergeNode.setNext(next);
+
+            block.firstInstruction = mergeNode;
         }
 
-        if (result instanceof MergeNode) {
-            EndNode end = currentGraph.add(new EndNode());
-            ((MergeNode) result).addForwardEnd(end);
-            result = end;
-        }
-        assert !(result instanceof MergeNode);
-        Debug.log("createTarget(%s, state) = %s", block, result);
+        MergeNode mergeNode = (MergeNode) block.firstInstruction;
+
+        // The EndNode for the newly merged edge.
+        EndNode result = currentGraph.add(new EndNode());
+        block.entryState.merge(mergeNode, stateAfter);
+        mergeNode.addForwardEnd(result);
+
+        Debug.log("createTarget %s: merging state, result: %s", block, result);
         return result;
     }
 
-    private ValueNode synchronizedObject(FrameStateAccess state, RiResolvedMethod target) {
+    /**
+     * Returns a block begin node with the specified state.  If the specified probability is 0, the block
+     * deoptimizes immediately.
+     */
+    private BeginNode createBlockTarget(double probability, Block block, FrameStateBuilder stateAfter) {
+        assert probability >= 0 && probability <= 1;
+        if (probability == 0) {
+            FrameStateBuilder state = stateAfter.copy();
+            state.clearNonLiveLocals(block.localsLiveIn);
+
+            BeginNode begin = currentGraph.add(new BeginNode());
+            DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile));
+            begin.setNext(deopt);
+            begin.setStateAfter(state.create(block.startBci));
+            return begin;
+        }
+
+        FixedNode target = createTarget(block, stateAfter);
+        assert !(target instanceof BeginNode);
+        BeginNode begin = currentGraph.add(new BeginNode());
+        begin.setNext(target);
+        return begin;
+    }
+
+    private ValueNode synchronizedObject(FrameStateBuilder state, RiResolvedMethod target) {
         if (isStatic(target.accessFlags())) {
             return append(ConstantNode.forCiConstant(target.holder().getEncoding(Representation.JavaClass), runtime, currentGraph));
         } else {
-            return state.localAt(0);
+            return state.loadLocal(0);
         }
     }
 
-    private void iterateAllBlocks() {
-        Block block;
-        while ((block = removeFromWorkList()) != null) {
-            // remove blocks that have no predecessors by the time it their bytecodes are parsed
-            if (block.firstInstruction == null) {
-                markVisited(block);
-                continue;
-            }
+    private void processBlock(Block block) {
+        // Ignore blocks that have no predecessors by the time it their bytecodes are parsed
+        if (block == null || block.firstInstruction == null) {
+            Debug.log("Ignoring block %s", block);
+            return;
+        }
+        Debug.log("Parsing block %s  firstInstruction: %s  loopHeader: %b", block, block.firstInstruction, block.isLoopHeader);
+
+        lastInstr = block.firstInstruction;
+        frameState = block.entryState;
+        currentBlock = block;
 
-            if (!isVisited(block)) {
-                markVisited(block);
-                // now parse the block
-                if (block.isLoopHeader) {
-                    LoopBeginNode begin = loopBegin(block);
-                    FrameState preLoopState = ((StateSplit) block.firstInstruction).stateAfter();
-                    FrameState loopState = preLoopState.duplicate(preLoopState.bci);
-                    begin.setStateAfter(loopState);
-                    loopState.insertLoopPhis(begin);
-                    lastInstr = begin;
-                } else {
-                    lastInstr = block.firstInstruction;
-                }
-                frameState.initializeFrom(((StateSplit) lastInstr).stateAfter());
-                assert lastInstr.next() == null : "instructions already appended at block " + block.blockID;
+        frameState.cleanupDeletedPhis();
+        if (lastInstr instanceof MergeNode) {
+            int bci = block.startBci;
+            if (block instanceof ExceptionBlock) {
+                bci = ((ExceptionBlock) block).deoptBci;
+            }
+            ((MergeNode) lastInstr).setStateAfter(frameState.create(bci));
+        }
 
-                if (block == returnBlock) {
-                    frameState.setRethrowException(false);
-                    createReturn();
-                } else if (block == unwindBlock) {
-                    frameState.setRethrowException(false);
-                    createUnwind();
-                } else if (block instanceof ExceptionBlock) {
-                    createExceptionDispatch((ExceptionBlock) block);
-                } else if (block instanceof DeoptBlock) {
-                    createDeopt();
-                } else {
-                    frameState.setRethrowException(false);
-                    iterateBytecodesForBlock(block);
-                }
-            }
+        if (block == returnBlock) {
+            frameState.setRethrowException(false);
+            createReturn();
+        } else if (block == unwindBlock) {
+            frameState.setRethrowException(false);
+            createUnwind();
+        } else if (block instanceof ExceptionBlock) {
+            createExceptionDispatch((ExceptionBlock) block);
+        } else {
+            frameState.setRethrowException(false);
+            iterateBytecodesForBlock(block);
         }
     }
 
     private void connectLoopEndToBegin() {
         for (LoopBeginNode begin : currentGraph.getNodes(LoopBeginNode.class)) {
             if (begin.loopEnds().isEmpty()) {
-//              This can happen with degenerated loops like this one:
-//              for (;;) {
-//                  try {
-//                      break;
-//                  } catch (UnresolvedException iioe) {
-//                  }
-//              }
-
-                // Remove the loop begin or transform it into a merge.
-                assert begin.forwardEndCount() > 0;
+                // Remove loop header without loop ends.
+                // This can happen with degenerated loops like this one:
+                // for (;;) {
+                //     try {
+                //         break;
+                //     } catch (UnresolvedException iioe) {
+                //     }
+                // }
+                assert begin.forwardEndCount() == 1;
                 currentGraph.reduceDegenerateLoopBegin(begin);
             } else {
-                begin.stateAfter().simplifyLoopState();
+                // Delete unnecessary loop phi functions, i.e., phi functions where all inputs are either the same or the phi itself.
+                for (PhiNode phi : begin.stateAfter().values().filter(PhiNode.class).snapshot()) {
+                    checkRedundantPhi(phi);
+                }
             }
         }
     }
 
-    private static LoopBeginNode loopBegin(Block block) {
-        LoopBeginNode loopBegin = (LoopBeginNode) ((EndNode) block.firstInstruction.next()).merge();
-        return loopBegin;
-    }
+    private static void checkRedundantPhi(PhiNode phiNode) {
+        if (phiNode.isDeleted() || phiNode.valueCount() == 1) {
+            return;
+        }
 
-    private void createDeopt() {
-        append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile)));
+        ValueNode singleValue = phiNode.singleValue();
+        if (singleValue != null) {
+            Collection<PhiNode> phiUsages = phiNode.usages().filter(PhiNode.class).snapshot();
+            ((StructuredGraph) phiNode.graph()).replaceFloating(phiNode, singleValue);
+            for (PhiNode phi : phiUsages) {
+                checkRedundantPhi(phi);
+            }
+        }
     }
 
     private void createUnwind() {
@@ -1480,9 +1453,30 @@
     }
 
     private void iterateBytecodesForBlock(Block block) {
-        assert frameState != null;
+        if (block.isLoopHeader) {
+            // Create the loop header block, which later will merge the backward branches of the loop.
+            EndNode preLoopEnd = currentGraph.add(new EndNode());
+            LoopBeginNode loopBegin = currentGraph.add(new LoopBeginNode());
+            lastInstr.setNext(preLoopEnd);
+            // Add the single non-loop predecessor of the loop header.
+            loopBegin.addForwardEnd(preLoopEnd);
+            lastInstr = loopBegin;
 
-        currentBlock = block;
+            // Create phi functions for all local variables and operand stack slots.
+            frameState.insertLoopPhis(loopBegin);
+            loopBegin.setStateAfter(frameState.create(block.startBci));
+
+            // We have seen all forward branches. All subsequent backward branches will merge to the loop header.
+            // This ensures that the loop header has exactly one non-loop predecessor.
+            block.firstInstruction = loopBegin;
+            // We need to preserve the frame state builder of the loop header so that we can merge values for
+            // phi functions, so make a copy of it.
+            block.entryState = frameState.copy();
+
+            Debug.log("  created loop header %s", loopBegin);
+        }
+        assert lastInstr.next() == null : "instructions already appended at block " + block;
+        Debug.log("  frameState: %s", frameState);
 
         int endBCI = stream.endBCI();
 
@@ -1737,7 +1731,7 @@
             case IFNULL         : genIfNull(Condition.EQ); break;
             case IFNONNULL      : genIfNull(Condition.NE); break;
             case GOTO_W         : genGoto(); break;
-            case JSR_W          : genJsr(stream.readFarBranchDest()); break;
+            case JSR_W          : genJsr(stream.readBranchDest()); break;
             case BREAKPOINT:
                 throw new CiBailout("concurrent setting of breakpoint");
             default:
@@ -1769,31 +1763,4 @@
     private void genArrayLength() {
         frameState.ipush(append(currentGraph.add(new ArrayLengthNode(frameState.apop()))));
     }
-
-    /**
-     * Adds a block to the worklist, if it is not already in the worklist.
-     * This method will keep the worklist topologically stored (i.e. the lower
-     * DFNs are earlier in the list).
-     * @param block the block to add to the work list
-     */
-    private void addToWorkList(Block block) {
-        if (!isOnWorkList(block)) {
-            markOnWorkList(block);
-            sortIntoWorkList(block);
-        }
-    }
-
-    private void sortIntoWorkList(Block top) {
-        workList.offer(top);
-    }
-
-    /**
-     * Removes the next block from the worklist. The list is sorted topologically, so the
-     * block with the lowest depth first number in the list will be removed and returned.
-     * @return the next block from the worklist; {@code null} if there are no blocks
-     * in the worklist
-     */
-    private Block removeFromWorkList() {
-        return workList.poll();
-    }
 }
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/JsrScope.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/JsrScope.java	Wed Mar 07 10:02:33 2012 -0800
@@ -51,6 +51,10 @@
         return scope == 0;
     }
 
+    public boolean isPrefixOf(JsrScope other) {
+        return (scope & other.scope) == scope;
+    }
+
     public JsrScope pop() {
         return new JsrScope(scope >>> 16);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/bytecode/BytecodeLookupSwitch.java	Wed Mar 07 10:02:33 2012 -0800
@@ -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.max.graal.java.bytecode;
+
+/**
+ * A utility for processing {@link Bytecodes#LOOKUPSWITCH} bytecodes.
+ */
+public class BytecodeLookupSwitch extends BytecodeSwitch {
+    private static final int OFFSET_TO_NUMBER_PAIRS = 4;
+    private static final int OFFSET_TO_FIRST_PAIR_MATCH = 8;
+    private static final int OFFSET_TO_FIRST_PAIR_OFFSET = 12;
+    private static final int PAIR_SIZE = 8;
+
+    /**
+     * Constructor for a {@link BytecodeStream}.
+     * @param stream the {@code BytecodeStream} containing the switch instruction
+     * @param bci the index in the stream of the switch instruction
+     */
+    public BytecodeLookupSwitch(BytecodeStream stream, int bci) {
+        super(stream, bci);
+    }
+
+    @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);
+    }
+
+    @Override
+    public int keyAt(int i) {
+        return stream.readInt(alignedBci + OFFSET_TO_FIRST_PAIR_MATCH + PAIR_SIZE * i);
+    }
+
+    @Override
+    public int numberOfCases() {
+        return stream.readInt(alignedBci + OFFSET_TO_NUMBER_PAIRS);
+    }
+
+    @Override
+    public int size() {
+        return alignedBci + OFFSET_TO_FIRST_PAIR_MATCH + PAIR_SIZE * numberOfCases() - bci;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/bytecode/BytecodeStream.java	Wed Mar 07 10:02:33 2012 -0800
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.java.bytecode;
+
+/**
+ * A utility class that makes iterating over bytecodes and reading operands
+ * simpler and less error prone. For example, it handles the {@link Bytecodes#WIDE} instruction
+ * and wide variants of instructions internally.
+ */
+public final class BytecodeStream {
+
+    private final byte[] code;
+    private int opcode;
+    private int curBCI;
+    private int nextBCI;
+
+    /**
+     * Creates a new {@code BytecodeStream} for the specified bytecode.
+     * @param code the array of bytes that contains the bytecode
+     */
+    public BytecodeStream(byte[] code) {
+        assert code != null;
+        this.code = code;
+        setBCI(0);
+    }
+
+    /**
+     * Advances to the next bytecode.
+     */
+    public void next() {
+        setBCI(nextBCI);
+    }
+
+    /**
+     * Gets the next bytecode index (no side-effects).
+     * @return the next bytecode index
+     */
+    public int nextBCI() {
+        return nextBCI;
+    }
+
+    /**
+     * Gets the current bytecode index.
+     * @return the current bytecode index
+     */
+    public int currentBCI() {
+        return curBCI;
+    }
+
+    /**
+     * Gets the bytecode index of the end of the code.
+     * @return the index of the end of the code
+     */
+    public int endBCI() {
+        return code.length;
+    }
+
+    /**
+     * Gets the current opcode. This method will never return the
+     * {@link Bytecodes#WIDE WIDE} opcode, but will instead
+     * return the opcode that is modified by the {@code WIDE} opcode.
+     * @return the current opcode; {@link Bytecodes#END} if at or beyond the end of the code
+     */
+    public int currentBC() {
+        if (opcode == Bytecodes.WIDE) {
+            return Bytes.beU1(code, curBCI + 1);
+        } else {
+            return opcode;
+        }
+    }
+
+    /**
+     * Reads the index of a local variable for one of the load or store instructions.
+     * The WIDE modifier is handled internally.
+     * @return the index of the local variable
+     */
+    public int readLocalIndex() {
+        // read local variable index for load/store
+        if (opcode == Bytecodes.WIDE) {
+            return Bytes.beU2(code, curBCI + 2);
+        }
+        return Bytes.beU1(code, curBCI + 1);
+    }
+
+    /**
+     * Read the delta for an {@link Bytecodes#IINC} bytecode.
+     * @return the delta for the {@code IINC}
+     */
+    public int readIncrement() {
+        // read the delta for the iinc bytecode
+        if (opcode == Bytecodes.WIDE) {
+            return Bytes.beS2(code, curBCI + 4);
+        }
+        return Bytes.beS1(code, curBCI + 2);
+    }
+
+    /**
+     * Read the destination of a {@link Bytecodes#GOTO} or {@code IF} instructions.
+     * @return the destination bytecode index
+     */
+    public int readBranchDest() {
+        // reads the destination for a branch bytecode
+        if (opcode == Bytecodes.GOTO_W || opcode == Bytecodes.JSR_W) {
+            return curBCI + Bytes.beS4(code, curBCI + 1);
+        } else {
+            return curBCI + Bytes.beS2(code, curBCI + 1);
+        }
+    }
+
+    /**
+     * Read a signed 4-byte integer from the bytecode stream at the specified bytecode index.
+     * @param bci the bytecode index
+     * @return the integer value
+     */
+    public int readInt(int bci) {
+        // reads a 4-byte signed value
+        return Bytes.beS4(code, bci);
+    }
+
+    /**
+     * Reads an unsigned, 1-byte value from the bytecode stream at the specified bytecode index.
+     * @param bci the bytecode index
+     * @return the byte
+     */
+    public int readUByte(int bci) {
+        return Bytes.beU1(code, bci);
+    }
+
+    /**
+     * Reads a constant pool index for the current instruction.
+     * @return the constant pool index
+     */
+    public char readCPI() {
+        if (opcode == Bytecodes.LDC) {
+            return (char) Bytes.beU1(code, curBCI + 1);
+        }
+        return (char) Bytes.beU2(code, curBCI + 1);
+    }
+
+    /**
+     * Reads a signed, 1-byte value for the current instruction (e.g. BIPUSH).
+     * @return the byte
+     */
+    public byte readByte() {
+        return code[curBCI + 1];
+    }
+
+    /**
+     * Reads a signed, 2-byte short for the current instruction (e.g. SIPUSH).
+     * @return the short value
+     */
+    public short readShort() {
+        return (short) Bytes.beS2(code, curBCI + 1);
+    }
+
+    /**
+     * Sets the bytecode index to the specified value.
+     * If {@code bci} is beyond the end of the array, {@link #currentBC} will return
+     * {@link Bytecodes#END} and other methods may throw {@link ArrayIndexOutOfBoundsException}.
+     * @param bci the new bytecode index
+     */
+    public void setBCI(int bci) {
+        curBCI = bci;
+        if (curBCI < code.length) {
+            opcode = Bytes.beU1(code, bci);
+            nextBCI = bci + lengthOf();
+        } else {
+            opcode = Bytecodes.END;
+            nextBCI = curBCI;
+        }
+    }
+
+    /**
+     * Gets the length of the current bytecode.
+     */
+    private int lengthOf() {
+        int length = Bytecodes.lengthOf(opcode);
+        if (length == 0) {
+            switch (opcode) {
+                case Bytecodes.TABLESWITCH: {
+                    return new BytecodeTableSwitch(this, curBCI).size();
+                }
+                case Bytecodes.LOOKUPSWITCH: {
+                    return new BytecodeLookupSwitch(this, curBCI).size();
+                }
+                case Bytecodes.WIDE: {
+                    int opc = Bytes.beU1(code, curBCI + 1);
+                    if (opc == Bytecodes.RET) {
+                        return 4;
+                    } else if (opc == Bytecodes.IINC) {
+                        return 6;
+                    } else {
+                        return 4; // a load or store bytecode
+                    }
+                }
+                default:
+                    throw new Error("unknown variable-length bytecode: " + opcode);
+            }
+        }
+        return length;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/bytecode/BytecodeSwitch.java	Wed Mar 07 10:02:33 2012 -0800
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.java.bytecode;
+
+/**
+ * An abstract class that provides the state and methods common to {@link Bytecodes#LOOKUPSWITCH}
+ * and {@link Bytecodes#TABLESWITCH} instructions.
+ */
+public abstract class BytecodeSwitch {
+    /**
+     * The {@link BytecodeStream} containing the bytecode array.
+     */
+    protected final BytecodeStream stream;
+    /**
+     * Index of start of switch instruction.
+     */
+    protected final int bci;
+    /**
+     * Index of the start of the additional data for the switch instruction, aligned to a multiple of four from the method start.
+     */
+    protected final int alignedBci;
+
+    /**
+     * Constructor for a {@link BytecodeStream}.
+     * @param stream the {@code BytecodeStream} containing the switch instruction
+     * @param bci the index in the stream of the switch instruction
+     */
+    public BytecodeSwitch(BytecodeStream stream, int bci) {
+        this.stream = stream;
+        this.bci = bci;
+        this.alignedBci = (bci + 4) & 0xfffffffc;
+    }
+
+    /**
+     * Gets the current bytecode index.
+     * @return the current bytecode index
+     */
+    public int bci() {
+        return bci;
+    }
+
+    /**
+     * Gets the index of the instruction denoted by the {@code i}'th switch target.
+     * @param i index of the switch target
+     * @return the index of the instruction denoted by the {@code i}'th switch target
+     */
+    public int targetAt(int i) {
+        return bci + offsetAt(i);
+    }
+
+    /**
+     * Gets the index of the instruction for the default switch target.
+     * @return the index of the instruction for the default switch target
+     */
+    public int defaultTarget() {
+        return bci + defaultOffset();
+    }
+
+    /**
+     * 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();
+
+    /**
+     * Gets the key at {@code i}'th switch target index.
+     * @param i the switch target index
+     * @return the key at {@code i}'th switch target index
+     */
+    public abstract int keyAt(int i);
+
+    /**
+     * Gets the offset from the start of the switch instruction for the {@code i}'th switch target.
+     * @param i the switch target index
+     * @return the offset to the {@code i}'th switch target
+     */
+    public abstract int offsetAt(int i);
+
+    /**
+     * Gets the number of switch targets.
+     * @return the number of switch targets
+     */
+    public abstract int numberOfCases();
+
+    /**
+     * Gets the total size in bytes of the switch instruction.
+     * @return the total size in bytes of the switch instruction
+     */
+    public abstract int size();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/bytecode/BytecodeTableSwitch.java	Wed Mar 07 10:02:33 2012 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.java.bytecode;
+
+/**
+ * A utility for processing {@link Bytecodes#TABLESWITCH} bytecodes.
+ */
+public class BytecodeTableSwitch extends BytecodeSwitch {
+    private static final int OFFSET_TO_LOW_KEY = 4;
+    private static final int OFFSET_TO_HIGH_KEY = 8;
+    private static final int OFFSET_TO_FIRST_JUMP_OFFSET = 12;
+    private static final int JUMP_OFFSET_SIZE = 4;
+
+    /**
+     * Constructor for a {@link BytecodeStream}.
+     * @param stream the {@code BytecodeStream} containing the switch instruction
+     * @param bci the index in the stream of the switch instruction
+     */
+    public BytecodeTableSwitch(BytecodeStream stream, int bci) {
+        super(stream, bci);
+    }
+
+    /**
+     * Gets the low key of the table switch.
+     * @return the low key
+     */
+    public int lowKey() {
+        return stream.readInt(alignedBci + OFFSET_TO_LOW_KEY);
+    }
+
+    /**
+     * Gets the high key of the table switch.
+     * @return the high key
+     */
+    public int highKey() {
+        return stream.readInt(alignedBci + OFFSET_TO_HIGH_KEY);
+    }
+
+    @Override
+    public int keyAt(int i) {
+        return lowKey() + i;
+    }
+
+    @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);
+    }
+
+    @Override
+    public int numberOfCases() {
+        return highKey() - lowKey() + 1;
+    }
+
+    @Override
+    public int size() {
+        return alignedBci + OFFSET_TO_FIRST_JUMP_OFFSET + JUMP_OFFSET_SIZE * numberOfCases() - bci;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/bytecode/Bytecodes.java	Wed Mar 07 10:02:33 2012 -0800
@@ -0,0 +1,940 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.java.bytecode;
+
+import static com.oracle.max.graal.java.bytecode.Bytecodes.Flags.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.regex.*;
+
+/**
+ * The definitions of the bytecodes that are valid input to the compiler and
+ * related utility methods. This comprises two groups: the standard Java
+ * bytecodes defined by <a href=
+ * "http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html">
+ * Java Virtual Machine Specification</a>, and a set of <i>extended</i>
+ * bytecodes that support low-level programming, for example, memory barriers.
+ *
+ * The extended bytecodes are one or three bytes in size. The one-byte bytecodes
+ * follow the values in the standard set, with no gap. The three-byte extended
+ * bytecodes share a common first byte and carry additional instruction-specific
+ * information in the second and third bytes.
+ */
+public class Bytecodes {
+    public static final int NOP                  =   0; // 0x00
+    public static final int ACONST_NULL          =   1; // 0x01
+    public static final int ICONST_M1            =   2; // 0x02
+    public static final int ICONST_0             =   3; // 0x03
+    public static final int ICONST_1             =   4; // 0x04
+    public static final int ICONST_2             =   5; // 0x05
+    public static final int ICONST_3             =   6; // 0x06
+    public static final int ICONST_4             =   7; // 0x07
+    public static final int ICONST_5             =   8; // 0x08
+    public static final int LCONST_0             =   9; // 0x09
+    public static final int LCONST_1             =  10; // 0x0A
+    public static final int FCONST_0             =  11; // 0x0B
+    public static final int FCONST_1             =  12; // 0x0C
+    public static final int FCONST_2             =  13; // 0x0D
+    public static final int DCONST_0             =  14; // 0x0E
+    public static final int DCONST_1             =  15; // 0x0F
+    public static final int BIPUSH               =  16; // 0x10
+    public static final int SIPUSH               =  17; // 0x11
+    public static final int LDC                  =  18; // 0x12
+    public static final int LDC_W                =  19; // 0x13
+    public static final int LDC2_W               =  20; // 0x14
+    public static final int ILOAD                =  21; // 0x15
+    public static final int LLOAD                =  22; // 0x16
+    public static final int FLOAD                =  23; // 0x17
+    public static final int DLOAD                =  24; // 0x18
+    public static final int ALOAD                =  25; // 0x19
+    public static final int ILOAD_0              =  26; // 0x1A
+    public static final int ILOAD_1              =  27; // 0x1B
+    public static final int ILOAD_2              =  28; // 0x1C
+    public static final int ILOAD_3              =  29; // 0x1D
+    public static final int LLOAD_0              =  30; // 0x1E
+    public static final int LLOAD_1              =  31; // 0x1F
+    public static final int LLOAD_2              =  32; // 0x20
+    public static final int LLOAD_3              =  33; // 0x21
+    public static final int FLOAD_0              =  34; // 0x22
+    public static final int FLOAD_1              =  35; // 0x23
+    public static final int FLOAD_2              =  36; // 0x24
+    public static final int FLOAD_3              =  37; // 0x25
+    public static final int DLOAD_0              =  38; // 0x26
+    public static final int DLOAD_1              =  39; // 0x27
+    public static final int DLOAD_2              =  40; // 0x28
+    public static final int DLOAD_3              =  41; // 0x29
+    public static final int ALOAD_0              =  42; // 0x2A
+    public static final int ALOAD_1              =  43; // 0x2B
+    public static final int ALOAD_2              =  44; // 0x2C
+    public static final int ALOAD_3              =  45; // 0x2D
+    public static final int IALOAD               =  46; // 0x2E
+    public static final int LALOAD               =  47; // 0x2F
+    public static final int FALOAD               =  48; // 0x30
+    public static final int DALOAD               =  49; // 0x31
+    public static final int AALOAD               =  50; // 0x32
+    public static final int BALOAD               =  51; // 0x33
+    public static final int CALOAD               =  52; // 0x34
+    public static final int SALOAD               =  53; // 0x35
+    public static final int ISTORE               =  54; // 0x36
+    public static final int LSTORE               =  55; // 0x37
+    public static final int FSTORE               =  56; // 0x38
+    public static final int DSTORE               =  57; // 0x39
+    public static final int ASTORE               =  58; // 0x3A
+    public static final int ISTORE_0             =  59; // 0x3B
+    public static final int ISTORE_1             =  60; // 0x3C
+    public static final int ISTORE_2             =  61; // 0x3D
+    public static final int ISTORE_3             =  62; // 0x3E
+    public static final int LSTORE_0             =  63; // 0x3F
+    public static final int LSTORE_1             =  64; // 0x40
+    public static final int LSTORE_2             =  65; // 0x41
+    public static final int LSTORE_3             =  66; // 0x42
+    public static final int FSTORE_0             =  67; // 0x43
+    public static final int FSTORE_1             =  68; // 0x44
+    public static final int FSTORE_2             =  69; // 0x45
+    public static final int FSTORE_3             =  70; // 0x46
+    public static final int DSTORE_0             =  71; // 0x47
+    public static final int DSTORE_1             =  72; // 0x48
+    public static final int DSTORE_2             =  73; // 0x49
+    public static final int DSTORE_3             =  74; // 0x4A
+    public static final int ASTORE_0             =  75; // 0x4B
+    public static final int ASTORE_1             =  76; // 0x4C
+    public static final int ASTORE_2             =  77; // 0x4D
+    public static final int ASTORE_3             =  78; // 0x4E
+    public static final int IASTORE              =  79; // 0x4F
+    public static final int LASTORE              =  80; // 0x50
+    public static final int FASTORE              =  81; // 0x51
+    public static final int DASTORE              =  82; // 0x52
+    public static final int AASTORE              =  83; // 0x53
+    public static final int BASTORE              =  84; // 0x54
+    public static final int CASTORE              =  85; // 0x55
+    public static final int SASTORE              =  86; // 0x56
+    public static final int POP                  =  87; // 0x57
+    public static final int POP2                 =  88; // 0x58
+    public static final int DUP                  =  89; // 0x59
+    public static final int DUP_X1               =  90; // 0x5A
+    public static final int DUP_X2               =  91; // 0x5B
+    public static final int DUP2                 =  92; // 0x5C
+    public static final int DUP2_X1              =  93; // 0x5D
+    public static final int DUP2_X2              =  94; // 0x5E
+    public static final int SWAP                 =  95; // 0x5F
+    public static final int IADD                 =  96; // 0x60
+    public static final int LADD                 =  97; // 0x61
+    public static final int FADD                 =  98; // 0x62
+    public static final int DADD                 =  99; // 0x63
+    public static final int ISUB                 = 100; // 0x64
+    public static final int LSUB                 = 101; // 0x65
+    public static final int FSUB                 = 102; // 0x66
+    public static final int DSUB                 = 103; // 0x67
+    public static final int IMUL                 = 104; // 0x68
+    public static final int LMUL                 = 105; // 0x69
+    public static final int FMUL                 = 106; // 0x6A
+    public static final int DMUL                 = 107; // 0x6B
+    public static final int IDIV                 = 108; // 0x6C
+    public static final int LDIV                 = 109; // 0x6D
+    public static final int FDIV                 = 110; // 0x6E
+    public static final int DDIV                 = 111; // 0x6F
+    public static final int IREM                 = 112; // 0x70
+    public static final int LREM                 = 113; // 0x71
+    public static final int FREM                 = 114; // 0x72
+    public static final int DREM                 = 115; // 0x73
+    public static final int INEG                 = 116; // 0x74
+    public static final int LNEG                 = 117; // 0x75
+    public static final int FNEG                 = 118; // 0x76
+    public static final int DNEG                 = 119; // 0x77
+    public static final int ISHL                 = 120; // 0x78
+    public static final int LSHL                 = 121; // 0x79
+    public static final int ISHR                 = 122; // 0x7A
+    public static final int LSHR                 = 123; // 0x7B
+    public static final int IUSHR                = 124; // 0x7C
+    public static final int LUSHR                = 125; // 0x7D
+    public static final int IAND                 = 126; // 0x7E
+    public static final int LAND                 = 127; // 0x7F
+    public static final int IOR                  = 128; // 0x80
+    public static final int LOR                  = 129; // 0x81
+    public static final int IXOR                 = 130; // 0x82
+    public static final int LXOR                 = 131; // 0x83
+    public static final int IINC                 = 132; // 0x84
+    public static final int I2L                  = 133; // 0x85
+    public static final int I2F                  = 134; // 0x86
+    public static final int I2D                  = 135; // 0x87
+    public static final int L2I                  = 136; // 0x88
+    public static final int L2F                  = 137; // 0x89
+    public static final int L2D                  = 138; // 0x8A
+    public static final int F2I                  = 139; // 0x8B
+    public static final int F2L                  = 140; // 0x8C
+    public static final int F2D                  = 141; // 0x8D
+    public static final int D2I                  = 142; // 0x8E
+    public static final int D2L                  = 143; // 0x8F
+    public static final int D2F                  = 144; // 0x90
+    public static final int I2B                  = 145; // 0x91
+    public static final int I2C                  = 146; // 0x92
+    public static final int I2S                  = 147; // 0x93
+    public static final int LCMP                 = 148; // 0x94
+    public static final int FCMPL                = 149; // 0x95
+    public static final int FCMPG                = 150; // 0x96
+    public static final int DCMPL                = 151; // 0x97
+    public static final int DCMPG                = 152; // 0x98
+    public static final int IFEQ                 = 153; // 0x99
+    public static final int IFNE                 = 154; // 0x9A
+    public static final int IFLT                 = 155; // 0x9B
+    public static final int IFGE                 = 156; // 0x9C
+    public static final int IFGT                 = 157; // 0x9D
+    public static final int IFLE                 = 158; // 0x9E
+    public static final int IF_ICMPEQ            = 159; // 0x9F
+    public static final int IF_ICMPNE            = 160; // 0xA0
+    public static final int IF_ICMPLT            = 161; // 0xA1
+    public static final int IF_ICMPGE            = 162; // 0xA2
+    public static final int IF_ICMPGT            = 163; // 0xA3
+    public static final int IF_ICMPLE            = 164; // 0xA4
+    public static final int IF_ACMPEQ            = 165; // 0xA5
+    public static final int IF_ACMPNE            = 166; // 0xA6
+    public static final int GOTO                 = 167; // 0xA7
+    public static final int JSR                  = 168; // 0xA8
+    public static final int RET                  = 169; // 0xA9
+    public static final int TABLESWITCH          = 170; // 0xAA
+    public static final int LOOKUPSWITCH         = 171; // 0xAB
+    public static final int IRETURN              = 172; // 0xAC
+    public static final int LRETURN              = 173; // 0xAD
+    public static final int FRETURN              = 174; // 0xAE
+    public static final int DRETURN              = 175; // 0xAF
+    public static final int ARETURN              = 176; // 0xB0
+    public static final int RETURN               = 177; // 0xB1
+    public static final int GETSTATIC            = 178; // 0xB2
+    public static final int PUTSTATIC            = 179; // 0xB3
+    public static final int GETFIELD             = 180; // 0xB4
+    public static final int PUTFIELD             = 181; // 0xB5
+    public static final int INVOKEVIRTUAL        = 182; // 0xB6
+    public static final int INVOKESPECIAL        = 183; // 0xB7
+    public static final int INVOKESTATIC         = 184; // 0xB8
+    public static final int INVOKEINTERFACE      = 185; // 0xB9
+    public static final int XXXUNUSEDXXX         = 186; // 0xBA
+    public static final int NEW                  = 187; // 0xBB
+    public static final int NEWARRAY             = 188; // 0xBC
+    public static final int ANEWARRAY            = 189; // 0xBD
+    public static final int ARRAYLENGTH          = 190; // 0xBE
+    public static final int ATHROW               = 191; // 0xBF
+    public static final int CHECKCAST            = 192; // 0xC0
+    public static final int INSTANCEOF           = 193; // 0xC1
+    public static final int MONITORENTER         = 194; // 0xC2
+    public static final int MONITOREXIT          = 195; // 0xC3
+    public static final int WIDE                 = 196; // 0xC4
+    public static final int MULTIANEWARRAY       = 197; // 0xC5
+    public static final int IFNULL               = 198; // 0xC6
+    public static final int IFNONNULL            = 199; // 0xC7
+    public static final int GOTO_W               = 200; // 0xC8
+    public static final int JSR_W                = 201; // 0xC9
+    public static final int BREAKPOINT           = 202; // 0xCA
+
+    public static final int ILLEGAL = 255;
+    public static final int END = 256;
+
+    /**
+     * The last opcode defined by the JVM specification. To iterate over all JVM bytecodes:
+     * <pre>
+     *     for (int opcode = 0; opcode <= Bytecodes.LAST_JVM_OPCODE; ++opcode) {
+     *         //
+     *     }
+     * </pre>
+     */
+    public static final int LAST_JVM_OPCODE = JSR_W;
+
+    /**
+     * A collection of flags describing various bytecode attributes.
+     */
+    static class Flags {
+
+        /**
+         * Denotes an instruction that ends a basic block and does not let control flow fall through to its lexical successor.
+         */
+        static final int STOP = 0x00000001;
+
+        /**
+         * Denotes an instruction that ends a basic block and may let control flow fall through to its lexical successor.
+         * In practice this means it is a conditional branch.
+         */
+        static final int FALL_THROUGH = 0x00000002;
+
+        /**
+         * Denotes an instruction that has a 2 or 4 byte operand that is an offset to another instruction in the same method.
+         * This does not include the {@link Bytecodes#TABLESWITCH} or {@link Bytecodes#LOOKUPSWITCH} instructions.
+         */
+        static final int BRANCH = 0x00000004;
+
+        /**
+         * Denotes an instruction that reads the value of a static or instance field.
+         */
+        static final int FIELD_READ = 0x00000008;
+
+        /**
+         * Denotes an instruction that writes the value of a static or instance field.
+         */
+        static final int FIELD_WRITE = 0x00000010;
+
+        /**
+         * Denotes an instruction that is not defined in the JVM specification.
+         */
+        static final int EXTENSION = 0x00000020;
+
+        /**
+         * Denotes an instruction that can cause a trap.
+         */
+        static final int TRAP        = 0x00000080;
+        /**
+         * Denotes an instruction that is commutative.
+         */
+        static final int COMMUTATIVE = 0x00000100;
+        /**
+         * Denotes an instruction that is associative.
+         */
+        static final int ASSOCIATIVE = 0x00000200;
+        /**
+         * Denotes an instruction that loads an operand.
+         */
+        static final int LOAD        = 0x00000400;
+        /**
+         * Denotes an instruction that stores an operand.
+         */
+        static final int STORE       = 0x00000800;
+        /**
+         * Denotes the 4 INVOKE* instructions.
+         */
+        static final int INVOKE       = 0x00001000;
+    }
+
+    // Performs a sanity check that none of the flags overlap.
+    static {
+        int allFlags = 0;
+        try {
+            for (Field field : Flags.class.getDeclaredFields()) {
+                int flagsFilter = Modifier.FINAL | Modifier.STATIC;
+                if ((field.getModifiers() & flagsFilter) == flagsFilter && !field.isSynthetic()) {
+                    assert field.getType() == int.class : "Field is not int : " + field;
+                    final int flag = field.getInt(null);
+                    assert flag != 0;
+                    assert (flag & allFlags) == 0 : field.getName() + " has a value conflicting with another flag";
+                    allFlags |= flag;
+                }
+            }
+        } catch (Exception e) {
+            throw new InternalError(e.toString());
+        }
+    }
+
+    /**
+     * An array that maps from a bytecode value to a {@link String} for the corresponding instruction mnemonic.
+     * This will include the root instruction for the three-byte extended instructions.
+     */
+    private static final String[] nameArray = new String[256];
+
+    /**
+     * An array that maps from a bytecode value to the set of {@link Flags} for the corresponding instruction.
+     */
+    private static final int[] flagsArray = new int[256];
+
+    /**
+     * An array that maps from a bytecode value to the length in bytes for the corresponding instruction.
+     */
+    private static final int[] lengthArray = new int[256];
+
+    /**
+     * An array that maps from a bytecode value to the estimated complexity of the bytecode in terms of generated machine code.
+     */
+    private static final int[] compilationComplexityArray = new int[256];
+
+    // Checkstyle: stop
+    static {
+        def(NOP                 , "nop"             , "b"    , 0);
+        def(ACONST_NULL         , "aconst_null"     , "b"    , 0);
+        def(ICONST_M1           , "iconst_m1"       , "b"    , 0);
+        def(ICONST_0            , "iconst_0"        , "b"    , 0);
+        def(ICONST_1            , "iconst_1"        , "b"    , 0);
+        def(ICONST_2            , "iconst_2"        , "b"    , 0);
+        def(ICONST_3            , "iconst_3"        , "b"    , 0);
+        def(ICONST_4            , "iconst_4"        , "b"    , 0);
+        def(ICONST_5            , "iconst_5"        , "b"    , 0);
+        def(LCONST_0            , "lconst_0"        , "b"    , 0);
+        def(LCONST_1            , "lconst_1"        , "b"    , 0);
+        def(FCONST_0            , "fconst_0"        , "b"    , 0);
+        def(FCONST_1            , "fconst_1"        , "b"    , 0);
+        def(FCONST_2            , "fconst_2"        , "b"    , 0);
+        def(DCONST_0            , "dconst_0"        , "b"    , 0);
+        def(DCONST_1            , "dconst_1"        , "b"    , 0);
+        def(BIPUSH              , "bipush"          , "bc"   , 0);
+        def(SIPUSH              , "sipush"          , "bcc"  , 0);
+        def(LDC                 , "ldc"             , "bi"   , 0, TRAP);
+        def(LDC_W               , "ldc_w"           , "bii"  , 0, TRAP);
+        def(LDC2_W              , "ldc2_w"          , "bii"  , 0, TRAP);
+        def(ILOAD               , "iload"           , "bi"   , 0, LOAD);
+        def(LLOAD               , "lload"           , "bi"   , 0, LOAD);
+        def(FLOAD               , "fload"           , "bi"   , 0, LOAD);
+        def(DLOAD               , "dload"           , "bi"   , 0, LOAD);
+        def(ALOAD               , "aload"           , "bi"   , 0, LOAD);
+        def(ILOAD_0             , "iload_0"         , "b"    , 0, LOAD);
+        def(ILOAD_1             , "iload_1"         , "b"    , 0, LOAD);
+        def(ILOAD_2             , "iload_2"         , "b"    , 0, LOAD);
+        def(ILOAD_3             , "iload_3"         , "b"    , 0, LOAD);
+        def(LLOAD_0             , "lload_0"         , "b"    , 0, LOAD);
+        def(LLOAD_1             , "lload_1"         , "b"    , 0, LOAD);
+        def(LLOAD_2             , "lload_2"         , "b"    , 0, LOAD);
+        def(LLOAD_3             , "lload_3"         , "b"    , 0, LOAD);
+        def(FLOAD_0             , "fload_0"         , "b"    , 0, LOAD);
+        def(FLOAD_1             , "fload_1"         , "b"    , 0, LOAD);
+        def(FLOAD_2             , "fload_2"         , "b"    , 0, LOAD);
+        def(FLOAD_3             , "fload_3"         , "b"    , 0, LOAD);
+        def(DLOAD_0             , "dload_0"         , "b"    , 0, LOAD);
+        def(DLOAD_1             , "dload_1"         , "b"    , 0, LOAD);
+        def(DLOAD_2             , "dload_2"         , "b"    , 0, LOAD);
+        def(DLOAD_3             , "dload_3"         , "b"    , 0, LOAD);
+        def(ALOAD_0             , "aload_0"         , "b"    , 0, LOAD);
+        def(ALOAD_1             , "aload_1"         , "b"    , 0, LOAD);
+        def(ALOAD_2             , "aload_2"         , "b"    , 0, LOAD);
+        def(ALOAD_3             , "aload_3"         , "b"    , 0, LOAD);
+        def(IALOAD              , "iaload"          , "b"    , 0, TRAP);
+        def(LALOAD              , "laload"          , "b"    , 0, TRAP);
+        def(FALOAD              , "faload"          , "b"    , 0, TRAP);
+        def(DALOAD              , "daload"          , "b"    , 0, TRAP);
+        def(AALOAD              , "aaload"          , "b"    , 0, TRAP);
+        def(BALOAD              , "baload"          , "b"    , 0, TRAP);
+        def(CALOAD              , "caload"          , "b"    , 0, TRAP);
+        def(SALOAD              , "saload"          , "b"    , 0, TRAP);
+        def(ISTORE              , "istore"          , "bi"   , 0, STORE);
+        def(LSTORE              , "lstore"          , "bi"   , 0, STORE);
+        def(FSTORE              , "fstore"          , "bi"   , 0, STORE);
+        def(DSTORE              , "dstore"          , "bi"   , 0, STORE);
+        def(ASTORE              , "astore"          , "bi"   , 0, STORE);
+        def(ISTORE_0            , "istore_0"        , "b"    , 0, STORE);
+        def(ISTORE_1            , "istore_1"        , "b"    , 0, STORE);
+        def(ISTORE_2            , "istore_2"        , "b"    , 0, STORE);
+        def(ISTORE_3            , "istore_3"        , "b"    , 0, STORE);
+        def(LSTORE_0            , "lstore_0"        , "b"    , 0, STORE);
+        def(LSTORE_1            , "lstore_1"        , "b"    , 0, STORE);
+        def(LSTORE_2            , "lstore_2"        , "b"    , 0, STORE);
+        def(LSTORE_3            , "lstore_3"        , "b"    , 0, STORE);
+        def(FSTORE_0            , "fstore_0"        , "b"    , 0, STORE);
+        def(FSTORE_1            , "fstore_1"        , "b"    , 0, STORE);
+        def(FSTORE_2            , "fstore_2"        , "b"    , 0, STORE);
+        def(FSTORE_3            , "fstore_3"        , "b"    , 0, STORE);
+        def(DSTORE_0            , "dstore_0"        , "b"    , 0, STORE);
+        def(DSTORE_1            , "dstore_1"        , "b"    , 0, STORE);
+        def(DSTORE_2            , "dstore_2"        , "b"    , 0, STORE);
+        def(DSTORE_3            , "dstore_3"        , "b"    , 0, STORE);
+        def(ASTORE_0            , "astore_0"        , "b"    , 0, STORE);
+        def(ASTORE_1            , "astore_1"        , "b"    , 0, STORE);
+        def(ASTORE_2            , "astore_2"        , "b"    , 0, STORE);
+        def(ASTORE_3            , "astore_3"        , "b"    , 0, STORE);
+        def(IASTORE             , "iastore"         , "b"    , 3, TRAP);
+        def(LASTORE             , "lastore"         , "b"    , 3, TRAP);
+        def(FASTORE             , "fastore"         , "b"    , 3, TRAP);
+        def(DASTORE             , "dastore"         , "b"    , 3, TRAP);
+        def(AASTORE             , "aastore"         , "b"    , 4, TRAP);
+        def(BASTORE             , "bastore"         , "b"    , 3, TRAP);
+        def(CASTORE             , "castore"         , "b"    , 3, TRAP);
+        def(SASTORE             , "sastore"         , "b"    , 3, TRAP);
+        def(POP                 , "pop"             , "b"    , 0);
+        def(POP2                , "pop2"            , "b"    , 0);
+        def(DUP                 , "dup"             , "b"    , 0);
+        def(DUP_X1              , "dup_x1"          , "b"    , 0);
+        def(DUP_X2              , "dup_x2"          , "b"    , 0);
+        def(DUP2                , "dup2"            , "b"    , 0);
+        def(DUP2_X1             , "dup2_x1"         , "b"    , 0);
+        def(DUP2_X2             , "dup2_x2"         , "b"    , 0);
+        def(SWAP                , "swap"            , "b"    , 0);
+        def(IADD                , "iadd"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(LADD                , "ladd"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(FADD                , "fadd"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(DADD                , "dadd"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(ISUB                , "isub"            , "b"    , 1);
+        def(LSUB                , "lsub"            , "b"    , 1);
+        def(FSUB                , "fsub"            , "b"    , 1);
+        def(DSUB                , "dsub"            , "b"    , 1);
+        def(IMUL                , "imul"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(LMUL                , "lmul"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(FMUL                , "fmul"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(DMUL                , "dmul"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(IDIV                , "idiv"            , "b"    , 1, TRAP);
+        def(LDIV                , "ldiv"            , "b"    , 1, TRAP);
+        def(FDIV                , "fdiv"            , "b"    , 1);
+        def(DDIV                , "ddiv"            , "b"    , 1);
+        def(IREM                , "irem"            , "b"    , 1, TRAP);
+        def(LREM                , "lrem"            , "b"    , 1, TRAP);
+        def(FREM                , "frem"            , "b"    , 1);
+        def(DREM                , "drem"            , "b"    , 1);
+        def(INEG                , "ineg"            , "b"    , 1);
+        def(LNEG                , "lneg"            , "b"    , 1);
+        def(FNEG                , "fneg"            , "b"    , 1);
+        def(DNEG                , "dneg"            , "b"    , 1);
+        def(ISHL                , "ishl"            , "b"    , 1);
+        def(LSHL                , "lshl"            , "b"    , 1);
+        def(ISHR                , "ishr"            , "b"    , 1);
+        def(LSHR                , "lshr"            , "b"    , 1);
+        def(IUSHR               , "iushr"           , "b"    , 1);
+        def(LUSHR               , "lushr"           , "b"    , 1);
+        def(IAND                , "iand"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(LAND                , "land"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(IOR                 , "ior"             , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(LOR                 , "lor"             , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(IXOR                , "ixor"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(LXOR                , "lxor"            , "b"    , 1, COMMUTATIVE | ASSOCIATIVE);
+        def(IINC                , "iinc"            , "bic"  , 1, LOAD | STORE);
+        def(I2L                 , "i2l"             , "b"    , 1);
+        def(I2F                 , "i2f"             , "b"    , 1);
+        def(I2D                 , "i2d"             , "b"    , 1);
+        def(L2I                 , "l2i"             , "b"    , 1);
+        def(L2F                 , "l2f"             , "b"    , 1);
+        def(L2D                 , "l2d"             , "b"    , 1);
+        def(F2I                 , "f2i"             , "b"    , 1);
+        def(F2L                 , "f2l"             , "b"    , 1);
+        def(F2D                 , "f2d"             , "b"    , 1);
+        def(D2I                 , "d2i"             , "b"    , 1);
+        def(D2L                 , "d2l"             , "b"    , 1);
+        def(D2F                 , "d2f"             , "b"    , 1);
+        def(I2B                 , "i2b"             , "b"    , 1);
+        def(I2C                 , "i2c"             , "b"    , 1);
+        def(I2S                 , "i2s"             , "b"    , 1);
+        def(LCMP                , "lcmp"            , "b"    , 1);
+        def(FCMPL               , "fcmpl"           , "b"    , 1);
+        def(FCMPG               , "fcmpg"           , "b"    , 1);
+        def(DCMPL               , "dcmpl"           , "b"    , 1);
+        def(DCMPG               , "dcmpg"           , "b"    , 1);
+        def(IFEQ                , "ifeq"            , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(IFNE                , "ifne"            , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(IFLT                , "iflt"            , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(IFGE                , "ifge"            , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(IFGT                , "ifgt"            , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(IFLE                , "ifle"            , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(IF_ICMPEQ           , "if_icmpeq"       , "boo"  , 2, COMMUTATIVE | FALL_THROUGH | BRANCH);
+        def(IF_ICMPNE           , "if_icmpne"       , "boo"  , 2, COMMUTATIVE | FALL_THROUGH | BRANCH);
+        def(IF_ICMPLT           , "if_icmplt"       , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(IF_ICMPGE           , "if_icmpge"       , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(IF_ICMPGT           , "if_icmpgt"       , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(IF_ICMPLE           , "if_icmple"       , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(IF_ACMPEQ           , "if_acmpeq"       , "boo"  , 2, COMMUTATIVE | FALL_THROUGH | BRANCH);
+        def(IF_ACMPNE           , "if_acmpne"       , "boo"  , 2, COMMUTATIVE | FALL_THROUGH | BRANCH);
+        def(GOTO                , "goto"            , "boo"  , 1, STOP | BRANCH);
+        def(JSR                 , "jsr"             , "boo"  , 0, STOP | BRANCH);
+        def(RET                 , "ret"             , "bi"   , 0, STOP);
+        def(TABLESWITCH         , "tableswitch"     , ""     , 4, STOP);
+        def(LOOKUPSWITCH        , "lookupswitch"    , ""     , 4, STOP);
+        def(IRETURN             , "ireturn"         , "b"    , 1, TRAP | STOP);
+        def(LRETURN             , "lreturn"         , "b"    , 1, TRAP | STOP);
+        def(FRETURN             , "freturn"         , "b"    , 1, TRAP | STOP);
+        def(DRETURN             , "dreturn"         , "b"    , 1, TRAP | STOP);
+        def(ARETURN             , "areturn"         , "b"    , 1, TRAP | STOP);
+        def(RETURN              , "return"          , "b"    , 1, TRAP | STOP);
+        def(GETSTATIC           , "getstatic"       , "bjj"  , 2, TRAP | FIELD_READ);
+        def(PUTSTATIC           , "putstatic"       , "bjj"  , 2, TRAP | FIELD_WRITE);
+        def(GETFIELD            , "getfield"        , "bjj"  , 2, TRAP | FIELD_READ);
+        def(PUTFIELD            , "putfield"        , "bjj"  , 2, TRAP | FIELD_WRITE);
+        def(INVOKEVIRTUAL       , "invokevirtual"   , "bjj"  , 7, TRAP | INVOKE);
+        def(INVOKESPECIAL       , "invokespecial"   , "bjj"  , 5, TRAP | INVOKE);
+        def(INVOKESTATIC        , "invokestatic"    , "bjj"  , 5, TRAP | INVOKE);
+        def(INVOKEINTERFACE     , "invokeinterface" , "bjja_", 7, TRAP | INVOKE);
+        def(XXXUNUSEDXXX        , "xxxunusedxxx"    , ""     , 0);
+        def(NEW                 , "new"             , "bii"  , 6, TRAP);
+        def(NEWARRAY            , "newarray"        , "bc"   , 6, TRAP);
+        def(ANEWARRAY           , "anewarray"       , "bii"  , 6, TRAP);
+        def(ARRAYLENGTH         , "arraylength"     , "b"    , 2, TRAP);
+        def(ATHROW              , "athrow"          , "b"    , 5, TRAP | STOP);
+        def(CHECKCAST           , "checkcast"       , "bii"  , 3, TRAP);
+        def(INSTANCEOF          , "instanceof"      , "bii"  , 4, TRAP);
+        def(MONITORENTER        , "monitorenter"    , "b"    , 5, TRAP);
+        def(MONITOREXIT         , "monitorexit"     , "b"    , 5, TRAP);
+        def(WIDE                , "wide"            , ""     , 0);
+        def(MULTIANEWARRAY      , "multianewarray"  , "biic" , 6, TRAP);
+        def(IFNULL              , "ifnull"          , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(IFNONNULL           , "ifnonnull"       , "boo"  , 2, FALL_THROUGH | BRANCH);
+        def(GOTO_W              , "goto_w"          , "boooo", 1, STOP | BRANCH);
+        def(JSR_W               , "jsr_w"           , "boooo", 0, STOP | BRANCH);
+        def(BREAKPOINT          , "breakpoint"      , "b"    , 0, TRAP);
+    }
+    // Checkstyle: resume
+
+    /**
+     * Determines if an opcode is commutative.
+     * @param opcode the opcode to check
+     * @return {@code true} iff commutative
+     */
+    public static boolean isCommutative(int opcode) {
+        return (flagsArray[opcode & 0xff] & COMMUTATIVE) != 0;
+    }
+
+    /**
+     * Gets the length of an instruction denoted by a given opcode.
+     *
+     * @param opcode an instruction opcode
+     * @return the length of the instruction denoted by {@code opcode}. If {@code opcode} is an illegal instruction or denotes a
+     *         variable length instruction (e.g. {@link #TABLESWITCH}), then 0 is returned.
+     */
+    public static int lengthOf(int opcode) {
+        return lengthArray[opcode & 0xff];
+    }
+
+    /**
+     * Gets the compilation complexity for a given opcode.
+     * @param opcode an opcode
+     * @return a value >= 0
+     */
+    public static int compilationComplexity(int opcode) {
+        return compilationComplexityArray[opcode & 0xff];
+    }
+
+    /**
+     * Gets the lower-case mnemonic for a given opcode.
+     *
+     * @param opcode an opcode
+     * @return the mnemonic for {@code opcode} or {@code "<illegal opcode: " + opcode + ">"} if {@code opcode} is not a legal opcode
+     */
+    public static String nameOf(int opcode) throws IllegalArgumentException {
+        String name = nameArray[opcode & 0xff];
+        if (name == null) {
+            return "<illegal opcode: " + opcode + ">";
+        }
+        return name;
+    }
+
+    /**
+     * Allocation-free version of {@linkplain #nameOf(int)}.
+     * @param opcode an opcode.
+     * @return the mnemonic for {@code opcode} or {@code "<illegal opcode>"} if {@code opcode} is not a legal opcode.
+     */
+    public static String baseNameOf(int opcode) {
+        String name = nameArray[opcode & 0xff];
+        if (name == null) {
+            return "<illegal opcode>";
+        }
+        return name;
+    }
+
+    /**
+     * Gets the opcode corresponding to a given mnemonic.
+     *
+     * @param name an opcode mnemonic
+     * @return the opcode corresponding to {@code mnemonic}
+     * @throws IllegalArgumentException if {@code name} does not denote a valid opcode
+     */
+    public static int valueOf(String name) {
+        for (int opcode = 0; opcode < nameArray.length; ++opcode) {
+            if (name.equalsIgnoreCase(nameArray[opcode])) {
+                return opcode;
+            }
+        }
+        throw new IllegalArgumentException("No opcode for " + name);
+    }
+
+    /**
+     * Determines if a given opcode denotes an instruction that can cause an implicit exception.
+     *
+     * @param opcode an opcode to test
+     * @return {@code true} iff {@code opcode} can cause an implicit exception, {@code false} otherwise
+     */
+    public static boolean canTrap(int opcode) {
+        return (flagsArray[opcode & 0xff] & TRAP) != 0;
+    }
+
+    /**
+     * Determines if a given opcode denotes an instruction that loads a local variable to the operand stack.
+     *
+     * @param opcode an opcode to test
+     * @return {@code true} iff {@code opcode} loads a local variable to the operand stack, {@code false} otherwise
+     */
+    public static boolean isLoad(int opcode) {
+        return (flagsArray[opcode & 0xff] & LOAD) != 0;
+    }
+
+    /**
+     * Determines if a given opcode denotes an instruction that ends a basic block and does not let control flow fall
+     * through to its lexical successor.
+     *
+     * @param opcode an opcode to test
+     * @return {@code true} iff {@code opcode} properly ends a basic block
+     */
+    public static boolean isStop(int opcode) {
+        return (flagsArray[opcode & 0xff] & STOP) != 0;
+    }
+
+    /**
+     * Determines if a given opcode denotes an instruction that stores a value to a local variable
+     * after popping it from the operand stack.
+     *
+     * @param opcode an opcode to test
+     * @return {@code true} iff {@code opcode} stores a value to a local variable, {@code false} otherwise
+     */
+    public static boolean isInvoke(int opcode) {
+        return (flagsArray[opcode & 0xff] & INVOKE) != 0;
+    }
+
+    /**
+     * Determines if a given opcode denotes an instruction that stores a value to a local variable
+     * after popping it from the operand stack.
+     *
+     * @param opcode an opcode to test
+     * @return {@code true} iff {@code opcode} stores a value to a local variable, {@code false} otherwise
+     */
+    public static boolean isStore(int opcode) {
+        return (flagsArray[opcode & 0xff] & STORE) != 0;
+    }
+
+    /**
+     * Determines if a given opcode is an instruction that delimits a basic block.
+     *
+     * @param opcode an opcode to test
+     * @return {@code true} iff {@code opcode} delimits a basic block
+     */
+    public static boolean isBlockEnd(int opcode) {
+        return (flagsArray[opcode & 0xff] & (STOP | FALL_THROUGH)) != 0;
+    }
+
+    /**
+     * Determines if a given opcode is an instruction that has a 2 or 4 byte operand that is an offset to another
+     * instruction in the same method. This does not include the {@linkplain #TABLESWITCH switch} instructions.
+     *
+     * @param opcode an opcode to test
+     * @return {@code true} iff {@code opcode} is a branch instruction with a single operand
+     */
+    public static boolean isBranch(int opcode) {
+        return (flagsArray[opcode & 0xff] & BRANCH) != 0;
+    }
+
+    /**
+     * Determines if a given opcode denotes a conditional branch.
+     * @param opcode
+     * @return {@code true} iff {@code opcode} is a conditional branch
+     */
+    public static boolean isConditionalBranch(int opcode) {
+        return (flagsArray[opcode & 0xff] & FALL_THROUGH) != 0;
+    }
+
+    /**
+     * Determines if a given opcode denotes a standard bytecode. A standard bytecode is
+     * defined in the JVM specification.
+     *
+     * @param opcode an opcode to test
+     * @return {@code true} iff {@code opcode} is a standard bytecode
+     */
+    public static boolean isStandard(int opcode) {
+        return (flagsArray[opcode & 0xff] & EXTENSION) == 0;
+    }
+
+    /**
+     * Determines if a given opcode denotes an extended bytecode.
+     *
+     * @param opcode an opcode to test
+     * @return {@code true} if {@code opcode} is an extended bytecode
+     */
+    public static boolean isExtended(int opcode) {
+        return (flagsArray[opcode & 0xff] & EXTENSION) != 0;
+    }
+
+    /**
+     * Determines if a given opcode is a three-byte extended bytecode.
+     *
+     * @param opcode an opcode to test
+     * @return {@code true} if {@code (opcode & ~0xff) != 0}
+     */
+    public static boolean isThreeByteExtended(int opcode) {
+        return (opcode & ~0xff) != 0;
+    }
+
+    /**
+     * Gets the arithmetic operator name for a given opcode. If {@code opcode} does not denote an
+     * arithmetic instruction, then the {@linkplain #nameOf(int) name} of the opcode is returned
+     * instead.
+     *
+     * @param op an opcode
+     * @return the arithmetic operator name
+     */
+    public static String operator(int op) {
+        // Checkstyle: stop
+        switch (op) {
+            // arithmetic ops
+            case IADD : // fall through
+            case LADD : // fall through
+            case FADD : // fall through
+            case DADD : return "+";
+            case ISUB : // fall through
+            case LSUB : // fall through
+            case FSUB : // fall through
+            case DSUB : return "-";
+            case IMUL : // fall through
+            case LMUL : // fall through
+            case FMUL : // fall through
+            case DMUL : return "*";
+            case IDIV : // fall through
+            case LDIV : // fall through
+            case FDIV : // fall through
+            case DDIV : return "/";
+            case IREM : // fall through
+            case LREM : // fall through
+            case FREM : // fall through
+            case DREM : return "%";
+            // shift ops
+            case ISHL : // fall through
+            case LSHL : return "<<";
+            case ISHR : // fall through
+            case LSHR : return ">>";
+            case IUSHR: // fall through
+            case LUSHR: return ">>>";
+            // logic ops
+            case IAND : // fall through
+            case LAND : return "&";
+            case IOR  : // fall through
+            case LOR  : return "|";
+            case IXOR : // fall through
+            case LXOR : return "^";
+        }
+        // Checkstyle: resume
+        return nameOf(op);
+    }
+
+    /**
+     * Defines a bytecode by entering it into the arrays that record its name, length and flags.
+     *
+     * @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);
+    }
+
+    /**
+     * Defines a bytecode by entering it into the arrays that record its name, length and flags.
+     *
+     * @param name instruction name (lower case)
+     * @param format encodes the length of the instruction
+     * @param flags the set of {@link Flags} associated with the instruction
+     */
+    private static void def(int opcode, String name, String format, int compilationComplexity, int flags) {
+        assert nameArray[opcode] == null : "opcode " + opcode + " is already bound to name " + nameArray[opcode];
+        nameArray[opcode] = name;
+        int instructionLength = format.length();
+        lengthArray[opcode] = instructionLength;
+        compilationComplexityArray[opcode] = compilationComplexity;
+        Bytecodes.flagsArray[opcode] = flags;
+
+        assert !isConditionalBranch(opcode) || isBranch(opcode) : "a conditional branch must also be a branch";
+    }
+
+    /**
+     * Utility for ensuring that the extended opcodes are contiguous and follow on directly
+     * from the standard JVM opcodes. If these conditions do not hold for the input source
+     * file, then it is modified 'in situ' to fix the problem.
+     *
+     * @param args {@code args[0]} is the path to this source file
+     */
+    public static void main(String[] args) throws Exception {
+        Method findWorkspaceDirectory = Class.forName("com.sun.max.ide.JavaProject").getDeclaredMethod("findWorkspaceDirectory");
+        File base = new File((File) findWorkspaceDirectory.invoke(null), "com.oracle.max.cri/src");
+        File file = new File(base, Bytecodes.class.getName().replace('.', File.separatorChar) + ".java").getAbsoluteFile();
+
+        Pattern opcodeDecl = Pattern.compile("(\\s*public static final int )(\\w+)(\\s*=\\s*)(\\d+)(;.*)");
+
+        BufferedReader br = new BufferedReader(new FileReader(file));
+        CharArrayWriter buffer = new CharArrayWriter((int) file.length());
+        PrintWriter out = new PrintWriter(buffer);
+        String line;
+        int lastExtendedOpcode = BREAKPOINT;
+        boolean modified = false;
+        int section = 0;
+        while ((line = br.readLine()) != null) {
+            if (section == 0) {
+                if (line.equals("    // Start extended bytecodes")) {
+                    section = 1;
+                }
+            } else if (section == 1) {
+                if (line.equals("    // End extended bytecodes")) {
+                    section = 2;
+                } else {
+                    Matcher matcher = opcodeDecl.matcher(line);
+                    if (matcher.matches()) {
+                        String name = matcher.group(2);
+                        String value = matcher.group(4);
+                        int opcode = Integer.parseInt(value);
+                        if (nameArray[opcode] == null || !nameArray[opcode].equalsIgnoreCase(name)) {
+                            throw new RuntimeException("Missing definition of name and flags for " + opcode + ":" + name + " -- " + nameArray[opcode]);
+                        }
+                        if (opcode != lastExtendedOpcode + 1) {
+                            System.err.println("Fixed declaration of opcode " + name + " to be " + (lastExtendedOpcode + 1) + " (was " + value + ")");
+                            opcode = lastExtendedOpcode + 1;
+                            line = line.substring(0, matcher.start(4)) + opcode + line.substring(matcher.end(4));
+                            modified = true;
+                        }
+
+                        if (opcode >= 256) {
+                            throw new RuntimeException("Exceeded maximum opcode value with " + name);
+                        }
+
+                        lastExtendedOpcode = opcode;
+                    }
+                }
+            }
+
+            out.println(line);
+        }
+        if (section == 0) {
+            throw new RuntimeException("Did not find line starting extended bytecode declarations:\n\n    // Start extended bytecodes");
+        } else if (section == 1) {
+            throw new RuntimeException("Did not find line ending extended bytecode declarations:\n\n    // End extended bytecodes");
+        }
+
+        if (modified) {
+            out.flush();
+            FileWriter fileWriter = new FileWriter(file);
+            fileWriter.write(buffer.toCharArray());
+            fileWriter.close();
+
+            System.out.println("Modified: " + file);
+        }
+
+
+        // Uncomment to print out visitor method declarations:
+//        for (int opcode = 0; opcode < flags.length; ++opcode) {
+//            if (isExtension(opcode)) {
+//                String visitorParams = length(opcode) == 1 ? "" : "int index";
+//                System.out.println("@Override");
+//                System.out.println("protected void " + name(opcode) + "(" + visitorParams + ") {");
+//                System.out.println("}");
+//                System.out.println();
+//            }
+//        }
+
+        // Uncomment to print out visitor method declarations:
+//        for (int opcode = 0; opcode < flags.length; ++opcode) {
+//            if (isExtension(opcode)) {
+//                System.out.println("case " + name(opcode).toUpperCase() + ": {");
+//                String arg = "";
+//                int length = length(opcode);
+//                if (length == 2) {
+//                    arg = "readUnsigned1()";
+//                } else if (length == 3) {
+//                    arg = "readUnsigned2()";
+//                }
+//                System.out.println("    bytecodeVisitor." + name(opcode) + "(" + arg + ");");
+//                System.out.println("    break;");
+//                System.out.println("}");
+//            }
+//        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/bytecode/Bytes.java	Wed Mar 07 10:02:33 2012 -0800
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.java.bytecode;
+
+/**
+ * A collection of utility methods for dealing with bytes, particularly in byte arrays.
+ */
+public class Bytes {
+    /**
+     * Gets a signed 1-byte value.
+     * @param data the array containing the data
+     * @param bci the start index of the value to retrieve
+     * @return the signed 1-byte value at index {@code bci} in array {@code data}
+     */
+    public static int beS1(byte[] data, int bci) {
+        return data[bci];
+    }
+
+    /**
+     * Gets a signed 2-byte big-endian value.
+     * @param data the array containing the data
+     * @param bci the start index of the value to retrieve
+     * @return the signed 2-byte, big-endian, value at index {@code bci} in array {@code data}
+     */
+    public static int beS2(byte[] data, int bci) {
+        return (data[bci] << 8) | (data[bci + 1] & 0xff);
+    }
+
+    /**
+     * Gets an unsigned 1-byte value.
+     * @param data the array containing the data
+     * @param bci the start index of the value to retrieve
+     * @return the unsigned 1-byte value at index {@code bci} in array {@code data}
+     */
+    public static int beU1(byte[] data, int bci) {
+        return data[bci] & 0xff;
+    }
+
+    /**
+     * Gets an unsigned 2-byte big-endian value.
+     * @param data the array containing the data
+     * @param bci the start index of the value to retrieve
+     * @return the unsigned 2-byte, big-endian, value at index {@code bci} in array {@code data}
+     */
+    public static int beU2(byte[] data, int bci) {
+        return ((data[bci] & 0xff) << 8) | (data[bci + 1] & 0xff);
+    }
+
+    /**
+     * Gets a signed 4-byte big-endian value.
+     * @param data the array containing the data
+     * @param bci the start index of the value to retrieve
+     * @return the signed 4-byte, big-endian, value at index {@code bci} in array {@code data}
+     */
+    public static int beS4(byte[] data, int bci) {
+        return (data[bci] << 24) | ((data[bci + 1] & 0xff) << 16) | ((data[bci + 2] & 0xff) << 8) | (data[bci + 3] & 0xff);
+    }
+
+    /**
+     * Gets either a signed 2-byte or a signed 4-byte big-endian value.
+     * @param data the array containing the data
+     * @param bci the start index of the value to retrieve
+     * @param fourByte if true, this method will return a 4-byte value
+     * @return the signed 2 or 4-byte, big-endian, value at index {@code bci} in array {@code data}
+     */
+    public static int beSVar(byte[] data, int bci, boolean fourByte) {
+        if (fourByte) {
+            return beS4(data, bci);
+        } else {
+            return beS2(data, bci);
+        }
+    }
+}
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/package-info.java	Wed Mar 07 09:50:36 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- */
-package com.oracle.max.graal.java;
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java	Wed Mar 07 10:02:33 2012 -0800
@@ -28,7 +28,6 @@
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.graph.iterators.*;
-import com.oracle.max.graal.nodes.PhiNode.PhiType;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.virtual.*;
 
@@ -36,7 +35,7 @@
  * The {@code FrameState} class encapsulates the frame state (i.e. local variables and
  * operand stack) at a particular point in the abstract interpretation.
  */
-public final class FrameState extends Node implements FrameStateAccess, Node.IterableNodeType, LIRLowerable {
+public final class FrameState extends Node implements Node.IterableNodeType, LIRLowerable {
 
     protected final int localsSize;
 
@@ -114,9 +113,11 @@
         this.stackSize = stackSize;
         final ValueNode[] newValues = new ValueNode[locals.length + stackSize];
         for (int i = 0; i < locals.length; i++) {
+            assert locals[i] == null || !locals[i].isDeleted();
             newValues[i] = locals[i];
         }
         for (int i = 0; i < stackSize; i++) {
+            assert stack[i] == null || !stack[i].isDeleted();
             newValues[localsSize + i] = stack[i];
         }
         this.values = new NodeInputList<>(this, newValues);
@@ -126,6 +127,10 @@
         assert !rethrowException || stackSize == 1 : "must have exception on top of the stack";
     }
 
+    public NodeIterable<ValueNode> values() {
+        return values;
+    }
+
     public FrameState outerFrameState() {
         return outerFrameState;
     }
@@ -135,15 +140,7 @@
         this.outerFrameState = x;
     }
 
-    public FrameState outermostFrameState() {
-        FrameState fs = this;
-        while (fs.outerFrameState() != null) {
-            fs = fs.outerFrameState();
-        }
-        return fs;
-    }
-
-    public void setValueAt(int i, ValueNode x) {
+    private void setValueAt(int i, ValueNode x) {
         values.set(i, x);
     }
 
@@ -199,18 +196,22 @@
         return other;
     }
 
-    @Override
-    public FrameState duplicateWithException(int newBci, ValueNode exceptionObject) {
-        return duplicateModified(newBci, true, CiKind.Void, exceptionObject);
-    }
-
     /**
      * Creates a copy of this frame state with one stack element of type popKind popped from the stack and the
      * values in pushedValues pushed on the stack. The pushedValues are expected to be in slot encoding: a long
      * or double is followed by a null slot.
      */
     public FrameState duplicateModified(int newBci, boolean newRethrowException, CiKind popKind, ValueNode... pushedValues) {
-        int popSlots = popKind == CiKind.Void ? 0 : isTwoSlot(popKind) ? 2 : 1;
+        int popSlots = 0;
+        if (popKind != CiKind.Void) {
+            if (stackAt(stackSize() - 1) == null) {
+                popSlots = 2;
+            } else {
+                popSlots = 1;
+            }
+            assert stackAt(stackSize() - popSlots).kind().stackKind() == popKind.stackKind();
+        }
+
         int pushSlots = pushedValues.length;
         FrameState other = graph().add(new FrameState(method, newBci, localsSize, stackSize - popSlots + pushSlots, newRethrowException, false));
         for (int i = 0; i < localsSize; i++) {
@@ -228,40 +229,6 @@
         return other;
     }
 
-    public boolean isCompatibleWith(FrameStateAccess other) {
-        if (stackSize() != other.stackSize() || localsSize() != other.localsSize()) {
-            return false;
-        }
-        for (int i = 0; i < stackSize(); i++) {
-            ValueNode x = stackAt(i);
-            ValueNode y = other.stackAt(i);
-            if (x != y && ValueUtil.typeMismatch(x, y)) {
-                return false;
-            }
-        }
-        if (other.outerFrameState() != outerFrameState()) {
-            return false;
-        }
-        return true;
-    }
-
-    public boolean equals(FrameStateAccess other) {
-        if (stackSize() != other.stackSize() || localsSize() != other.localsSize()) {
-            return false;
-        }
-        for (int i = 0; i < stackSize(); i++) {
-            ValueNode x = stackAt(i);
-            ValueNode y = other.stackAt(i);
-            if (x != y) {
-                return false;
-            }
-        }
-        if (other.outerFrameState() != outerFrameState()) {
-            return false;
-        }
-        return true;
-    }
-
     /**
      * Gets the size of the local variables.
      */
@@ -277,52 +244,14 @@
     }
 
     /**
-     * Invalidates the local variable at the specified index. If the specified index refers to a doubleword local, then
-     * invalidates the high word as well.
-     *
-     * @param i the index of the local to invalidate
-     */
-    public void invalidateLocal(int i) {
-        // note that for double word locals, the high slot should already be null
-        // unless the local is actually dead and the high slot is being reused;
-        // in either case, it is not necessary to null the high slot
-        setValueAt(i, null);
-    }
-
-    /**
-     * Stores a given local variable at the specified index. If the value is a {@linkplain CiKind#isDoubleWord() double word},
-     * then the next local variable index is also overwritten.
-     *
-     * @param i the index at which to store
-     * @param x the instruction which produces the value for the local
-     */
-    // TODO this duplicates code in FrameStateBuilder and needs to go away
-    public void storeLocal(int i, ValueNode x) {
-        assert i < localsSize : "local variable index out of range: " + i;
-        invalidateLocal(i);
-        setValueAt(i, x);
-        if (isTwoSlot(x.kind())) {
-            // (tw) if this was a double word then kill i+1
-            setValueAt(i + 1, null);
-        }
-        if (i > 0) {
-            // if there was a double word at i - 1, then kill it
-            ValueNode p = localAt(i - 1);
-            if (p != null && isTwoSlot(p.kind())) {
-                setValueAt(i - 1, null);
-            }
-        }
-    }
-
-    /**
      * Gets the value in the local variables at the specified index.
      *
      * @param i the index into the locals
      * @return the instruction that produced the value for the specified local
      */
     public ValueNode localAt(int i) {
-        assert i < localsSize : "local variable index out of range: " + i;
-        return valueAt(i);
+        assert i >= 0 && i < localsSize : "local variable index out of range: " + i;
+        return values.get(i);
     }
 
     /**
@@ -332,233 +261,38 @@
      * @return the instruction at the specified position in the stack
      */
     public ValueNode stackAt(int i) {
-        assert i >= 0 && i < (localsSize + stackSize);
-        return valueAt(localsSize + i);
-    }
-
-    /**
-     * Inserts a phi statement into the stack at the specified stack index.
-     * @param block the block begin for which we are creating the phi
-     * @param i the index into the stack for which to create a phi
-     */
-    public PhiNode setupLoopPhiForStack(MergeNode block, int i) {
-        ValueNode p = stackAt(i);
-        if (p != null) {
-            if (p instanceof PhiNode) {
-                PhiNode phi = (PhiNode) p;
-                if (phi.merge() == block) {
-                    return phi;
-                }
-            }
-            PhiNode phi = graph().unique(new PhiNode(p.kind(), block, PhiType.Value));
-            phi.addInput(p);
-            setValueAt(localsSize + i, phi);
-            return phi;
-        }
-        return null;
-    }
-
-    /**
-     * Inserts a phi statement for the local at the specified index.
-     * @param block the block begin for which we are creating the phi
-     * @param i the index of the local variable for which to create the phi
-     */
-    public PhiNode setupLoopPhiForLocal(MergeNode block, int i) {
-        ValueNode p = localAt(i);
-        if (p instanceof PhiNode) {
-            PhiNode phi = (PhiNode) p;
-            if (phi.merge() == block) {
-                return phi;
-            }
-        }
-        PhiNode phi = graph().unique(new PhiNode(p.kind(), block, PhiType.Value));
-        phi.addInput(p);
-        storeLocal(i, phi);
-        return phi;
-    }
-
-    /**
-     * Gets the value at a specified index in the set of operand stack and local values represented by this frame.
-     * This method should only be used to iterate over all the values in this frame, irrespective of whether
-     * they are on the stack or in local variables.
-     * To iterate the stack slots, the {@link #stackAt(int)} and {@link #stackSize()} methods should be used.
-     * To iterate the local variables, the {@link #localAt(int)} and {@link #localsSize()} methods should be used.
-     *
-     * @param i a value in the range {@code [0 .. valuesSize()]}
-     * @return the value at index {@code i} which may be {@code null}
-     */
-    public ValueNode valueAt(int i) {
-        assert i < (localsSize + stackSize);
-        return values.isEmpty() ? null : values.get(i);
-    }
-
-    /**
-     * The number of operand stack slots and local variables in this frame.
-     * This method should typically only be used in conjunction with {@link #valueAt(int)}.
-     * To iterate the stack slots, the {@link #stackAt(int)} and {@link #stackSize()} methods should be used.
-     * To iterate the local variables, the {@link #localAt(int)} and {@link #localsSize()} methods should be used.
-     *
-     * @return the number of local variables in this frame
-     */
-    public int valuesSize() {
-        return localsSize + stackSize;
-    }
-
-    private boolean checkSize(FrameStateAccess other) {
-        assert other.stackSize() == stackSize() : "stack sizes do not match";
-        assert other.localsSize() == localsSize : "local sizes do not match";
-        return true;
-    }
-
-    public void merge(MergeNode block, FrameStateAccess other) {
-        assert checkSize(other);
-        for (int i = 0; i < valuesSize(); i++) {
-            ValueNode currentValue = valueAt(i);
-            ValueNode otherValue = other.valueAt(i);
-            if (currentValue != otherValue || block instanceof LoopBeginNode) {
-                if (block.isPhiAtMerge(currentValue)) {
-                    addToPhi((PhiNode) currentValue, otherValue, block instanceof LoopBeginNode);
-                } else {
-                    setValueAt(i, combineValues(currentValue, otherValue, block));
-                }
-            }
-        }
-    }
-
-    public void simplifyLoopState() {
-        for (PhiNode phi : values.filter(PhiNode.class).snapshot()) {
-            checkRedundantPhi(phi);
-        }
-    }
-
-    private static ValueNode combineValues(ValueNode currentValue, ValueNode otherValue, MergeNode block) {
-        if (currentValue == null || otherValue == null || currentValue.kind() != otherValue.kind()) {
-            return null;
-        }
-
-        PhiNode phi = currentValue.graph().add(new PhiNode(currentValue.kind(), block, PhiType.Value));
-        for (int j = 0; j < block.phiPredecessorCount(); ++j) {
-            phi.addInput(currentValue);
-        }
-        phi.addInput(otherValue);
-        assert phi.valueCount() == block.phiPredecessorCount() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.phiPredecessorCount();
-        return phi;
-    }
-
-    private static void addToPhi(PhiNode phiNode, ValueNode otherValue, boolean recursiveInvalidCheck) {
-        if (otherValue == null || otherValue.kind() != phiNode.kind()) {
-            if (recursiveInvalidCheck) {
-                deleteInvalidPhi(phiNode);
-            } else {
-                phiNode.replaceAtUsages(null);
-                phiNode.safeDelete();
-            }
-        } else {
-            phiNode.addInput(otherValue);
-        }
-    }
-
-    public static void deleteRedundantPhi(PhiNode redundantPhi, ValueNode phiValue) {
-        Collection<PhiNode> phiUsages = redundantPhi.usages().filter(PhiNode.class).snapshot();
-        ((StructuredGraph) redundantPhi.graph()).replaceFloating(redundantPhi, phiValue);
-        for (PhiNode phi : phiUsages) {
-            checkRedundantPhi(phi);
-        }
-    }
-
-    private static void checkRedundantPhi(PhiNode phiNode) {
-        if (phiNode.isDeleted() || phiNode.valueCount() == 1) {
-            return;
-        }
-
-        ValueNode singleValue = phiNode.singleValue();
-        if (singleValue != null) {
-            deleteRedundantPhi(phiNode, singleValue);
-        }
-    }
-
-    private static void deleteInvalidPhi(PhiNode phiNode) {
-        if (!phiNode.isDeleted()) {
-            Collection<PhiNode> phiUsages = phiNode.usages().filter(PhiNode.class).snapshot();
-            phiNode.replaceAtUsages(null);
-            phiNode.safeDelete();
-            for (Node n : phiUsages) {
-                deleteInvalidPhi((PhiNode) n);
-            }
-        }
+        assert i >= 0 && i < stackSize;
+        return values.get(localsSize + i);
     }
 
     public MergeNode block() {
         return usages().filter(MergeNode.class).first();
     }
 
-    public StateSplit stateSplit() {
-        return (StateSplit) usages().filterInterface(StateSplit.class).first();
-    }
-
     public NodeIterable<FrameState> innerFrameStates() {
         return usages().filter(FrameState.class);
     }
 
-    /**
-     * The interface implemented by a client of {@link FrameState#forEachPhi(MergeNode, PhiProcedure)} and
-     * {@link FrameState#forEachLivePhi(MergeNode, PhiProcedure)}.
-     */
-    public interface PhiProcedure {
-        boolean doPhi(PhiNode phi);
-    }
-
-    /**
-     * Checks whether this frame state has any {@linkplain PhiNode phi} statements.
-     */
-    public boolean hasPhis() {
-        for (int i = 0; i < valuesSize(); i++) {
-            ValueNode value = valueAt(i);
-            if (value instanceof PhiNode) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public String toDetailedString() {
-        StringBuilder sb = new StringBuilder();
-        String nl = String.format("%n");
-        sb.append("[bci: ").append(bci).append("]");
-        if (rethrowException()) {
-            sb.append(" rethrows Exception");
-        }
-        sb.append(nl);
-        for (int i = 0; i < localsSize(); ++i) {
-            ValueNode value = localAt(i);
-            sb.append(String.format("  local[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind().javaName, value));
-        }
-        for (int i = 0; i < stackSize(); ++i) {
-            ValueNode value = stackAt(i);
-            sb.append(String.format("  stack[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind().javaName, value));
-        }
-        return sb.toString();
-    }
-
     @Override
     public void generate(LIRGeneratorTool gen) {
         // Nothing to do, frame states are processed as part of the handling of AbstractStateSplit nodes.
     }
 
-    public static String toString(FrameState frameState) {
+    private static String toString(FrameState frameState) {
         StringBuilder sb = new StringBuilder();
         String nl = CiUtil.NEW_LINE;
         FrameState fs = frameState;
         while (fs != null) {
             CiUtil.appendLocation(sb, fs.method, fs.bci).append(nl);
-            for (int i = 0; i < fs.localsSize(); ++i) {
-                ValueNode value = fs.localAt(i);
-                sb.append(String.format("  local[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind().javaName, value));
+            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));
             }
-            for (int i = 0; i < fs.stackSize(); ++i) {
-                ValueNode value = fs.stackAt(i);
-                sb.append(String.format("  stack[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind().javaName, value));
+            sb.append("]").append(nl).append("stack: ");
+            for (int i = 0; i < fs.stackSize(); i++) {
+                sb.append(i == 0 ? "" : ", ").append(fs.stackAt(i) == null ? "_" : fs.stackAt(i).toString(Verbosity.Id));
             }
+            sb.append(nl);
             fs = fs.outerFrameState();
         }
         return sb.toString();
@@ -575,22 +309,6 @@
         }
     }
 
-    public void insertLoopPhis(LoopBeginNode loopBegin) {
-        for (int i = 0; i < stackSize(); i++) {
-            // always insert phis for the stack
-            ValueNode x = stackAt(i);
-            if (x != null) {
-                setupLoopPhiForStack(loopBegin, i);
-            }
-        }
-        for (int i = 0; i < localsSize(); i++) {
-            ValueNode x = localAt(i);
-            if (x != null) {
-                setupLoopPhiForLocal(loopBegin, i);
-            }
-        }
-    }
-
     @Override
     public Map<Object, Object> getDebugProperties() {
         Map<Object, Object> properties = super.getDebugProperties();
@@ -600,41 +318,27 @@
         } else {
             properties.put("method", "None");
         }
-        StringBuilder str = new StringBuilder();
+        StringBuilder sb = new StringBuilder();
         for (int i = 0; i < localsSize(); i++) {
-            str.append(i == 0 ? "" : ", ").append(localAt(i) == null ? "_" : localAt(i).toString(Verbosity.Id));
+            sb.append(i == 0 ? "" : ", ").append(localAt(i) == null ? "_" : localAt(i).toString(Verbosity.Id));
         }
-        properties.put("locals", str.toString());
-        str = new StringBuilder();
+        properties.put("locals", sb.toString());
+        sb = new StringBuilder();
         for (int i = 0; i < stackSize(); i++) {
-            str.append(i == 0 ? "" : ", ").append(stackAt(i) == null ? "_" : stackAt(i).toString(Verbosity.Id));
+            sb.append(i == 0 ? "" : ", ").append(stackAt(i) == null ? "_" : stackAt(i).toString(Verbosity.Id));
         }
-        properties.put("stack", str.toString());
+        properties.put("stack", sb.toString());
         properties.put("rethrowException", rethrowException);
         properties.put("duringCall", duringCall);
         return properties;
     }
 
-    public CiCodePos toCodePos() {
-        FrameState caller = outerFrameState();
-        CiCodePos callerCodePos = null;
-        if (caller != null) {
-            callerCodePos = caller.toCodePos();
-        }
-        return new CiCodePos(callerCodePos, method, bci);
-    }
-
     @Override
     public boolean verify() {
         for (ValueNode value : values) {
+            assert assertTrue(value == null || !value.isDeleted(), "frame state must not contain deleted nodes");
             assert assertTrue(value == null || value instanceof VirtualObjectNode || (value.kind() != CiKind.Void && value.kind() != CiKind.Illegal), "unexpected value: %s", value);
         }
         return super.verify();
     }
-
-    // TODO this duplicates code in FrameStateBuilder and needs to go away
-    public static boolean isTwoSlot(CiKind kind) {
-        assert kind != CiKind.Void && kind != CiKind.Illegal;
-        return kind == CiKind.Long || kind == CiKind.Double;
-    }
 }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/PlaceholderNode.java	Wed Mar 07 09:50:36 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.nodes;
-
-import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.nodes.spi.*;
-import com.oracle.max.graal.nodes.type.*;
-
-
-public class PlaceholderNode extends AbstractStateSplit implements Node.IterableNodeType, LIRLowerable {
-
-    public PlaceholderNode() {
-        super(StampFactory.illegal());
-    }
-
-    @Override
-    public void generate(LIRGeneratorTool gen) {
-        // nothing to do
-    }
-}
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/FrameStateAccess.java	Wed Mar 07 09:50:36 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +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.graal.nodes.spi;
-
-import com.oracle.max.graal.nodes.*;
-
-public interface FrameStateAccess {
-
-    FrameState duplicate(int newBci);
-
-    int localsSize();
-
-    int stackSize();
-
-    boolean rethrowException();
-
-    ValueNode valueAt(int i);
-
-    ValueNode localAt(int i);
-
-    ValueNode stackAt(int i);
-
-    FrameState outerFrameState();
-
-    FrameState duplicateWithException(int bci, ValueNode exceptionObject);
-
-}
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Wed Mar 07 10:02:33 2012 -0800
@@ -50,6 +50,14 @@
 
     @Override
     public void dump(Object object, String message) {
+        try {
+            dumpSandboxed(object, message);
+        } catch (Throwable ex) {
+            TTY.println("CFGPrinter: Exception during output of " + message + ": " + ex);
+        }
+    }
+
+    public void dumpSandboxed(Object object, String message) {
         GraalCompiler compiler = Debug.contextLookup(GraalCompiler.class);
         if (compiler == null) {
             return;
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinter.java	Wed Mar 07 09:50:36 2012 -0800
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinter.java	Wed Mar 07 10:02:33 2012 -0800
@@ -32,7 +32,7 @@
 import com.oracle.max.graal.graph.Node.Verbosity;
 import com.oracle.max.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.max.graal.graph.NodeClass.Position;
-import com.oracle.max.graal.java.*;
+import com.oracle.max.graal.java.bytecode.*;
 import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 
--- a/mx/commands.py	Wed Mar 07 09:50:36 2012 -0800
+++ b/mx/commands.py	Wed Mar 07 10:02:33 2012 -0800
@@ -484,8 +484,8 @@
         
     build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product'
     mx.expand_project_in_args(args)  
-    if mx.java().debug:
-        args = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000'] + args
+    if mx.java().debug_port is not None:
+        args = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(mx.java().debug_port)] + args
     if _jacoco == 'on' or _jacoco == 'append':
         jacocoagent = mx.library("JACOCOAGENT", True)
         agentOptions = {
@@ -646,6 +646,7 @@
     parser = ArgumentParser(prog='mx gate');
     parser.add_argument('-n', '--omit-native-build', action='store_false', dest='buildNative', help='omit cleaning and building native code')
     parser.add_argument('-g', '--only-build-graalvm', action='store_false', dest='buildNonGraal', help='only build the Graal VM')
+    parser.add_argument('--jacocout', help='specify the output directory for jacoco report')
 
     args = parser.parse_args(args)
 
@@ -660,7 +661,7 @@
         t = Task('BuildJava')
         build(['--no-native'])
         tasks.append(t.stop())
-    
+        global _jacoco
         for vmbuild in ['fastdebug', 'product']:
             global _vmbuild
             _vmbuild = vmbuild
@@ -674,19 +675,35 @@
             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([])
             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.group + ' ' + 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())
 
         t = Task('Checkstyle')
         if mx.checkstyle([]) != 0:
--- a/mx/projects	Wed Mar 07 09:50:36 2012 -0800
+++ b/mx/projects	Wed Mar 07 10:02:33 2012 -0800
@@ -1,32 +1,4 @@
-# Library specification format:
-#
-#     library@<name>@<prop>=<value>
-#
-# Library properties (* = required):
-#
-#    *path: the file system path for the library to appear on a class path
-#     urls: a comma seperated list of URLs from which the library can be downloaded
-#     optional: if "true" then this library will be omitted from a class path if it doesn't exist on the file system and no URLs are specified
-#     eclipse.container: the name of the Eclipse library container corresponding to the library
-#
-# Project specification format:
-#
-#     project@<name>@<prop>=<value>
-#
-# The name of a project also denotes the directory it is in.
-#
-# Project properties:
-#
-#    *sourceDirs: a comma separated list of source directoriy names (relative to the project directory)
-#     dependencies: a comma separated list of the libraries and project the project depends upon (transitive dependencies may be omitted)
-#     eclipse.output: the output directory name (relative to the project directory)
-#     checkstyle: the project whose Checkstyle configuration (i.e. <project>/.checkstyle_checks.xml) is used
-#
-# The eclipse.* properties are only used when generating Eclipse project configuration files.
-#
-# Values can use environment variables with the syntax used in a Bash shell script.
-#
-
+# The format of this file is described in the documentation for my.py.
 
 library@JDK_TOOLS@path=${JAVA_HOME}/lib/tools.jar
 library@JDK_TOOLS@optional=true
@@ -55,91 +27,107 @@
 project@com.oracle.max.graal.hotspot@sourceDirs=src
 project@com.oracle.max.graal.hotspot@dependencies=com.oracle.max.graal.snippets
 project@com.oracle.max.graal.hotspot@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.hotspot@javaCompliance=1.7
 
 # graal.graph
 project@com.oracle.max.graal.graph@subDir=graal
 project@com.oracle.max.graal.graph@sourceDirs=src
 project@com.oracle.max.graal.graph@dependencies=com.oracle.max.graal.debug,JUNIT
+project@com.oracle.max.graal.graph@javaCompliance=1.7
 
 # graal.debug
 project@com.oracle.max.graal.debug@subDir=graal
 project@com.oracle.max.graal.debug@sourceDirs=src
 project@com.oracle.max.graal.debug@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.debug@javaCompliance=1.7
 
 # graal.lir
 project@com.oracle.max.graal.lir@subDir=graal
 project@com.oracle.max.graal.lir@sourceDirs=src
 project@com.oracle.max.graal.lir@dependencies=com.oracle.max.asm,com.oracle.max.graal.nodes
 project@com.oracle.max.graal.lir@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.lir@javaCompliance=1.7
 
 # graal.lir.amd64
 project@com.oracle.max.graal.lir.amd64@subDir=graal
 project@com.oracle.max.graal.lir.amd64@sourceDirs=src
 project@com.oracle.max.graal.lir.amd64@dependencies=com.oracle.max.graal.lir
 project@com.oracle.max.graal.lir.amd64@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.lir.amd64@javaCompliance=1.7
 
 # graal.alloc
 project@com.oracle.max.graal.alloc@subDir=graal
 project@com.oracle.max.graal.alloc@sourceDirs=src
 project@com.oracle.max.graal.alloc@dependencies=com.oracle.max.graal.lir
 project@com.oracle.max.graal.alloc@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.alloc@javaCompliance=1.7
 
 # graal.snippets
 project@com.oracle.max.graal.snippets@subDir=graal
 project@com.oracle.max.graal.snippets@sourceDirs=src,test
 project@com.oracle.max.graal.snippets@dependencies=com.oracle.max.graal.printer
 project@com.oracle.max.graal.snippets@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.snippets@javaCompliance=1.7
 
 # graal.nodes
 project@com.oracle.max.graal.nodes@subDir=graal
 project@com.oracle.max.graal.nodes@sourceDirs=src,test
 project@com.oracle.max.graal.nodes@dependencies=com.oracle.max.cri,com.oracle.max.graal.graph
 project@com.oracle.max.graal.nodes@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.nodes@javaCompliance=1.7
 
 # graal.compiler
 project@com.oracle.max.graal.compiler@subDir=graal
 project@com.oracle.max.graal.compiler@sourceDirs=src
 project@com.oracle.max.graal.compiler@dependencies=com.oracle.max.graal.lir.amd64,com.oracle.max.graal.alloc
 project@com.oracle.max.graal.compiler@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.compiler@javaCompliance=1.7
 
 # graal.java
 project@com.oracle.max.graal.java@subDir=graal
 project@com.oracle.max.graal.java@sourceDirs=src
 project@com.oracle.max.graal.java@dependencies=com.oracle.max.graal.compiler
 project@com.oracle.max.graal.java@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.java@javaCompliance=1.7
 
 # graal.printer
 project@com.oracle.max.graal.printer@subDir=graal
 project@com.oracle.max.graal.printer@sourceDirs=src
 project@com.oracle.max.graal.printer@dependencies=com.oracle.max.graal.java
 project@com.oracle.max.graal.printer@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.printer@javaCompliance=1.7
 
 # graal.test
 project@com.oracle.max.graal.tests@subDir=graal
 project@com.oracle.max.graal.tests@sourceDirs=src
 project@com.oracle.max.graal.tests@dependencies=com.oracle.max.graal.printer
 project@com.oracle.max.graal.tests@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.tests@javaCompliance=1.7
 
 # graal.jtt
 project@com.oracle.max.graal.jtt@subDir=graal
 project@com.oracle.max.graal.jtt@sourceDirs=src
 project@com.oracle.max.graal.jtt@dependencies=JUNIT
 project@com.oracle.max.graal.jtt@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.graal.jtt@javaCompliance=1.7
 
 # max.asm
 project@com.oracle.max.asm@subDir=graal
 project@com.oracle.max.asm@sourceDirs=src
 project@com.oracle.max.asm@dependencies=com.oracle.max.criutils
 project@com.oracle.max.asm@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.asm@javaCompliance=1.7
 
 # max.cri
 project@com.oracle.max.cri@subDir=graal
 project@com.oracle.max.cri@sourceDirs=src
 project@com.oracle.max.cri@dependencies=
 project@com.oracle.max.cri@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.cri@javaCompliance=1.7
 
 # max.criutils
 project@com.oracle.max.criutils@subDir=graal
 project@com.oracle.max.criutils@sourceDirs=src
 project@com.oracle.max.criutils@dependencies=com.oracle.max.cri
 project@com.oracle.max.criutils@checkstyle=com.oracle.max.graal.graph
+project@com.oracle.max.criutils@javaCompliance=1.7
--- a/mxtool/mx.py	Wed Mar 07 09:50:36 2012 -0800
+++ b/mxtool/mx.py	Wed Mar 07 10:02:33 2012 -0800
@@ -25,64 +25,104 @@
 #
 # ----------------------------------------------------------------------------------------------------
 #
-# mx is a command line tool inspired by mvn (http://maven.apache.org/)
-# and hg (http://mercurial.selenic.com/). It includes a mechanism for
-# managing the dependencies between a set of projects (like Maven)
-# as well as making it simple to run commands
-# (like hg is the interface to the Mercurial commands).
-#
-# The organizing principle of mx is a project suite. A suite is a directory
-# containing one or more projects. It's not coincidental that this closely
-# matches the layout of one or more projects in a Mercurial repository.
-# The configuration information for a suite lives in an 'mx' sub-directory
-# at the top level of the suite. 
-#
-# When launched, mx treats the current working directory as a suite.
-# This is the primary suite. All other suites are called included suites.
-#
-# The configuration files (i.e. in the 'mx' sub-directory) of a suite are:
-#
-#   projects    - Defines the projects and libraries in the suite and the dependencies between them
-#   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. 
-#   env         - A set of environment variable definitions.
-#
-# The includes and env files are typically not put under version control
-# as they usually contain local file-system paths.
-#
-# The projects file is like the pom.xml file from Maven except that
-# it is a properties file (not XML). Each non-comment line
-# in the file specifies an attribute of a project or library. The main 
-# difference between a project and a library is that the former contains
-# source code built by the mx tool where as the latter is an external
-# dependency. The format of the projects file is 
-#
-# Library specification format:
-#
-#     library@<name>@<prop>=<value>
-#
-# Built-in library properties (* = required):
-#
-#    *path: the file system path for the library to appear on a class path
-#     urls: a comma seperated list of URLs from which the library can be downloaded
-#     optional: if "true" then this library will be omitted from a class path if it doesn't exist on the file system and no URLs are specified
-#
-# Project specification format:
-#
-#     project@<name>@<prop>=<value>
-#
-# The name of a project also denotes the directory it is in.
-#
-# Built-in project properties:
-#
-#    *sourceDirs: a comma separated list of source directoriy names (relative to the project directory)
-#     dependencies: a comma separated list of the libraries and project the project depends upon (transitive dependencies may be omitted)
-#     checkstyle: the project whose Checkstyle configuration (i.e. <project>/.checkstyle_checks.xml) is used
-#
-# Other properties can be specified for projects and libraries for use by extension commands.
-#
-# Values can use environment variables with Bash syntax (e.g. ${HOME}).
+
+r"""
+mx is a command line tool inspired by mvn (http://maven.apache.org/)
+and hg (http://mercurial.selenic.com/). It includes a mechanism for
+managing the dependencies between a set of projects (like Maven)
+as well as making it simple to run commands
+(like hg is the interface to the Mercurial commands).
+
+The organizing principle of mx is a project suite. A suite is a directory
+containing one or more projects. It's not coincidental that this closely
+matches the layout of one or more projects in a Mercurial repository.
+The configuration information for a suite lives in an 'mx' sub-directory
+at the top level of the suite.
+
+When launched, mx treats the current working directory as a suite.
+This is the primary suite. All other suites are called included suites.
+
+The configuration files (i.e. in the 'mx' sub-directory) of a suite are:
+
+  projects
+      Defines the projects and libraries in the suite and the
+      dependencies between them.
+
+  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.
+
+  env
+      A set of environment variable definitions. These override any
+      existing environment variables.
+
+The includes and env files are typically not put under version control
+as they usually contain local file-system paths.
+
+The projects file is like the pom.xml file from Maven except that
+it is a properties file (not XML). Each non-comment line
+in the file specifies an attribute of a project or library. The main
+difference between a project and a library is that the former contains
+source code built by the mx tool where as the latter is an external
+dependency. The format of the projects file is
+
+Library specification format:
+
+    library@<name>@<prop>=<value>
+
+Built-in library properties (* = required):
+
+   *path
+        The file system path for the library to appear on a class path.
+
+    urls
+        A comma separated list of URLs from which the library (jar) can
+        be downloaded and saved in the location specified by 'path'.
+
+    optional
+        If "true" then this library will be omitted from a class path
+        if it doesn't exist on the file system and no URLs are specified.
+
+Project specification format:
+
+    project@<name>@<prop>=<value>
+
+The name of a project also denotes the directory it is in.
+
+Built-in project properties (* = required):
+
+    subDir
+        The sub-directory of the suite in which the project directory is
+        contained. If not specified, the project directory is directly
+        under the suite directory.
+
+   *sourceDirs
+        A comma separated list of source directory names (relative to
+        the project directory).
+
+    dependencies
+        A comma separated list of the libraries and project the project
+        depends upon (transitive dependencies should be omitted).
+
+    checkstyle
+        The project whose Checkstyle configuration
+        (i.e. <project>/.checkstyle_checks.xml) is used.
+
+    native
+        "true" if the project is native.
+
+    javaCompliance
+        The minimum JDK version (format: x.y) to which the project's
+        sources comply (required for non-native projects).
+
+Other properties can be specified for projects and libraries for use
+by extension commands.
+
+Property values can use environment variables with Bash syntax (e.g. ${HOME}).
+"""
 
 import sys, os, errno, time, subprocess, shlex, types, urllib2, contextlib, StringIO, zipfile, signal
 import shutil, fnmatch, re, xml.dom.minidom
@@ -107,31 +147,32 @@
     def __init__(self, suite, name):
         self.name = name
         self.suite = suite
-        
+
     def __str__(self):
         return self.name
-    
+
     def __eq__(self, other):
         return self.name == other.name
-    
+
     def __ne__(self, other):
         return self.name != other.name
 
     def __hash__(self):
         return hash(self.name)
-    
+
     def isLibrary(self):
         return isinstance(self, Library)
-    
+
 class Project(Dependency):
-    def __init__(self, suite, name, srcDirs, deps, dir):
+    def __init__(self, suite, name, srcDirs, deps, javaCompliance, dir):
         Dependency.__init__(self, suite, name)
         self.srcDirs = srcDirs
         self.deps = deps
         self.checkstyleProj = name
+        self.javaCompliance = JavaCompliance(javaCompliance) if javaCompliance is not None else None
         self.native = False
         self.dir = dir
-        
+
     def all_deps(self, deps, includeLibs, includeSelf=True):
         """
         Add the transitive set of dependencies for this project, including
@@ -152,7 +193,7 @@
         if not self in deps and includeSelf:
             deps.append(self)
         return deps
-    
+
     def _compute_max_dep_distances(self, name, distances, dist):
         currentDist = distances.get(name);
         if currentDist is None or currentDist < dist:
@@ -161,7 +202,7 @@
             if p is not None:
                 for dep in p.deps:
                     self._compute_max_dep_distances(dep, distances, dist + 1)
-                
+
     def canonical_deps(self):
         """
         Get the dependencies of this project that are not recursive (i.e. cannot be reached
@@ -174,19 +215,19 @@
             assert d > 0 or n == self.name
             if d == 1:
                 result.add(n)
-                
-            
+
+
         if len(result) == len(self.deps) and frozenset(self.deps) == result:
             return self.deps
         return result;
-    
+
 
     def source_dirs(self):
         """
         Get the directories in which the sources of this project are found.
         """
         return [join(self.dir, s) for s in self.srcDirs]
-        
+
     def output_dir(self):
         """
         Get the directory in which the class files of this project are found/placed.
@@ -195,6 +236,14 @@
             return None
         return join(self.dir, 'bin')
 
+    def jasmin_output_dir(self):
+        """
+        Get the directory in which the Jasmin assembled class files of this project are found/placed.
+        """
+        if self.native:
+            return None
+        return join(self.dir, 'jasmin_classes')
+
     def append_to_classpath(self, cp, resolve):
         if not self.native:
             cp.append(self.output_dir())
@@ -205,7 +254,7 @@
         self.path = path.replace('/', os.sep)
         self.urls = urls
         self.mustExist = mustExist
-    
+
     def get_path(self, resolve):
         path = self.path
         if not isabs(path):
@@ -214,14 +263,14 @@
             assert not len(self.urls) == 0, 'cannot find required library  ' + self.name + " " + path;
             print('Downloading ' + self.name + ' from ' + str(self.urls))
             download(path, self.urls)
-            
+
         return path
-        
+
     def append_to_classpath(self, cp, resolve):
         path = self.get_path(resolve)
         if exists(path) or not resolve:
             cp.append(path)
-    
+
 class Suite:
     def __init__(self, dir, primary):
         self.dir = dir
@@ -237,7 +286,7 @@
 
     def _load_projects(self, mxDir):
         libsMap = dict()
-        projsMap = dict() 
+        projsMap = dict()
         projectsFile = join(mxDir, 'projects')
         if not exists(projectsFile):
             return
@@ -246,9 +295,9 @@
                 line = line.strip()
                 if len(line) != 0 and line[0] != '#':
                     key, value = line.split('=', 1)
-                    
+
                     parts = key.split('@')
-                    
+
                     if len(parts) == 2:
                         pass
                     if len(parts) != 3:
@@ -260,31 +309,34 @@
                         m = libsMap
                     else:
                         abort('Property name does not start with "project@" or "library@": ' + key)
-                        
+
                     attrs = m.get(name)
                     if attrs is None:
                         attrs = dict()
                         m[name] = attrs
                     value = expandvars_in_property(value)
                     attrs[attr] = value
-                        
+
         def pop_list(attrs, name):
             v = attrs.pop(name, None)
             if v is None or len(v.strip()) == 0:
                 return []
             return [n.strip() for n in v.split(',')]
-        
+
         for name, attrs in projsMap.iteritems():
             srcDirs = pop_list(attrs, 'sourceDirs')
             deps = pop_list(attrs, 'dependencies')
+            javaCompliance = attrs.pop('javaCompliance', None)
             subDir = attrs.pop('subDir', None);
             if subDir is None:
                 dir = join(self.dir, name)
             else:
                 dir = join(self.dir, subDir, name)
-            p = Project(self, name, srcDirs, deps, dir)
+            p = Project(self, name, srcDirs, deps, javaCompliance, dir)
             p.checkstyleProj = attrs.pop('checkstyle', name)
             p.native = attrs.pop('native', '') == 'true'
+            if not p.native and p.javaCompliance is None:
+                abort('javaCompliance property required for non-native project ' + name)
             p.__dict__.update(attrs)
             self.projects.append(p)
 
@@ -295,15 +347,15 @@
             l = Library(self, name, path, mustExist, urls)
             l.__dict__.update(attrs)
             self.libs.append(l)
-        
+
     def _load_commands(self, mxDir):
         commands = join(mxDir, 'commands.py')
         if exists(commands):
             # temporarily extend the Python path
             sys.path.insert(0, mxDir)
-    
+
             mod = __import__('commands')
-    
+
             # revert the Python path
             del sys.path[0]
 
@@ -311,17 +363,17 @@
                 abort(commands + ' must define an mx_init(env) function')
             if hasattr(mod, 'mx_post_parse_cmd_line'):
                 self.mx_post_parse_cmd_line = mod.mx_post_parse_cmd_line
-                
+
             mod.mx_init()
             self.commands = mod
-                
+
     def _load_includes(self, mxDir):
         includes = join(mxDir, 'includes')
         if exists(includes):
             with open(includes) as f:
                 for line in f:
                     self.includes.append(expandvars_in_property(line.strip()))
-        
+
     def _load_env(self, mxDir):
         e = join(mxDir, 'env')
         if exists(e):
@@ -331,7 +383,7 @@
                     if len(line) != 0 and line[0] != '#':
                         key, value = line.split('=', 1)
                         os.environ[key.strip()] = expandvars_in_property(value.strip())
-    
+
     def _post_init(self, opts):
         mxDir = join(self.dir, 'mx')
         self._load_includes(mxDir)
@@ -348,7 +400,7 @@
             if existing is not None:
                 abort('cannot redefine library  ' + l.name)
             _libs[l.name] = l
-        
+
 def get_os():
     """
     Get a canonical form of sys.platform.
@@ -371,7 +423,7 @@
     if not _suites.has_key(dir):
         suite = Suite(dir, primary)
         _suites[dir] = suite
-        return suite 
+        return suite
 
 def suites():
     """
@@ -384,7 +436,7 @@
     Get the list of all loaded projects.
     """
     return _projects.values()
-    
+
 def project(name, fatalIfMissing=True):
     """
     Get the project for a given name. This will abort if the named project does
@@ -421,7 +473,7 @@
     path (e.g. downloading a missing library) if 'resolve' is true.
     """
     if names is None:
-        return _as_classpath(sorted_deps(True), resolve)
+        return _as_classpath(sorted_deps(includeLibs=True), resolve)
     deps = []
     if isinstance(names, types.StringTypes):
         project(names).all_deps(deps, True, includeSelf)
@@ -429,15 +481,20 @@
         for n in names:
             project(n).all_deps(deps, True, includeSelf)
     return _as_classpath(deps, resolve)
-    
-def sorted_deps(includeLibs=False):
+
+def sorted_deps(projectNames=None, includeLibs=False):
     """
-    Gets the loaded projects and libraries sorted such that dependencies
+    Gets projects and libraries sorted such that dependencies
     are before the projects that depend on them. Unless 'includeLibs' is
     true, libraries are omitted from the result.
     """
     deps = []
-    for p in _projects.itervalues():
+    if projectNames is None:
+        projects = _projects.values()
+    else:
+        projects = [project(name) for name in projectNames]
+
+    for p in projects:
         p.all_deps(deps, includeLibs)
     return deps
 
@@ -446,14 +503,15 @@
     # Override parent to append the list of available commands
     def format_help(self):
         return ArgumentParser.format_help(self) + _format_commands()
-    
-    
+
+
     def __init__(self):
         self.java_initialized = False
         ArgumentParser.__init__(self, prog='mx')
-    
+
         self.add_argument('-v', action='store_true', dest='verbose', help='enable verbose output')
-        self.add_argument('-d', action='store_true', dest='java_dbg', help='make Java processes wait on port 8000 for a debugger')
+        self.add_argument('--dbg', type=int, dest='java_dbg_port', help='make Java processes wait on <port> for a debugger', metavar='<port>')
+        self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"')
         self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='<arg>')
         self.add_argument('--cp-sfx', dest='cp_suffix', help='class path suffix', metavar='<arg>')
         self.add_argument('--J', dest='java_args', help='Java VM arguments (e.g. --J @-dsa)', metavar='@<args>', default=DEFAULT_JAVA_ARGS)
@@ -465,15 +523,15 @@
             # Time outs are (currently) implemented with Unix specific functionality
             self.add_argument('--timeout', help='Timeout (in seconds) for command', type=int, default=0, metavar='<secs>')
             self.add_argument('--ptimeout', help='Timeout (in seconds) for subprocesses', type=int, default=0, metavar='<secs>')
-        
+
     def _parse_cmd_line(self, args=None):
         if args is None:
             args = sys.argv[1:]
 
         self.add_argument('commandAndArgs', nargs=REMAINDER, metavar='command args...')
-        
+
         opts = self.parse_args()
-        
+
         # Give the timeout options a default value to avoid the need for hasattr() tests
         opts.__dict__.setdefault('timeout', 0)
         opts.__dict__.setdefault('ptimeout', 0)
@@ -486,13 +544,13 @@
 
         if opts.user_home is None or opts.user_home == '':
             abort('Could not find user home. Use --user-home option or ensure HOME environment variable is set.')
-    
+
         os.environ['JAVA_HOME'] = opts.java_home
         os.environ['HOME'] = opts.user_home
-        
+
         commandAndArgs = opts.__dict__.pop('commandAndArgs')
         return opts, commandAndArgs
-    
+
 def _format_commands():
     msg = '\navailable commands:\n\n'
     for cmd in sorted(commands.iterkeys()):
@@ -531,7 +589,7 @@
                 if e.errno == errno.EINTR:
                     continue
                 raise
-    
+
     def _returncode(status):
         if os.WIFSIGNALED(status):
             return -os.WTERMSIG(status)
@@ -540,7 +598,7 @@
         else:
             # Should never happen
             raise RuntimeError("Unknown child exit status!")
-        
+
     end = time.time() + timeout
     delay = 0.0005
     while True:
@@ -576,19 +634,19 @@
     Each line of the standard output and error streams of the subprocess are redirected to
     out and err if they are callable objects.
     """
-    
+
     assert isinstance(args, types.ListType), "'args' must be a list: " + str(args)
     for arg in args:
         assert isinstance(arg, types.StringTypes), 'argument is not a string: ' + str(arg)
-    
+
     if _opts.verbose:
         log(' '.join(args))
-        
+
     if timeout is None and _opts.ptimeout != 0:
         timeout = _opts.ptimeout
 
     global _currentSubprocess
-        
+
     try:
         # On Unix, the new subprocess should be in a separate group so that a timeout alarm
         # can use os.killpg() to kill the whole subprocess group
@@ -597,13 +655,13 @@
         if get_os() == 'windows':
             creationflags = subprocess.CREATE_NEW_PROCESS_GROUP
         else:
-            preexec_fn = os.setsid  
-        
+            preexec_fn = os.setsid
+
         if not callable(out) and not callable(err) and timeout is None:
             # The preexec_fn=os.setsid
             p = subprocess.Popen(args, cwd=cwd, preexec_fn=preexec_fn, creationflags=creationflags)
             _currentSubprocess = (p, args)
-	    retcode = waitOn(p)
+            retcode = waitOn(p)
         else:
             def redirect(stream, f):
                 for line in iter(stream.readline, ''):
@@ -641,12 +699,12 @@
         if _opts.verbose:
             raise subprocess.CalledProcessError(retcode, ' '.join(args))
         abort(retcode)
-        
+
     return retcode
 
 def exe_suffix(name):
     """
-    Gets the platform specific suffix for an executable 
+    Gets the platform specific suffix for an executable
     """
     if get_os() == 'windows':
         return name + '.exe'
@@ -664,12 +722,30 @@
     return name
 
 """
+A JavaCompliance simplifies comparing Java compliance values extracted from a JDK version string.
+"""
+class JavaCompliance:
+    def __init__(self, ver):
+        m = re.match('1\.(\d+).*', ver)
+        assert m is not None, 'not a recognized version string: ' + vstring
+        self.value = int(m.group(1))
+
+    def __str__ (self):
+        return '1.' + str(self.value)
+
+    def __cmp__ (self, other):
+        if isinstance(other, types.StringType):
+            other = JavaCompliance(other)
+
+        return cmp(self.value, other.value)
+
+"""
 A JavaConfig object encapsulates info on how Java commands are run.
 """
 class JavaConfig:
     def __init__(self, opts):
         self.jdk = opts.java_home
-        self.debug = opts.java_dbg
+        self.debug_port = opts.java_dbg_port
         self.java =  exe_suffix(join(self.jdk, 'bin', 'java'))
         self.javac = exe_suffix(join(self.jdk, 'bin', 'javac'))
         self.javap = exe_suffix(join(self.jdk, 'bin', 'javap'))
@@ -679,11 +755,11 @@
 
         def delAtAndSplit(s):
             return shlex.split(s.lstrip('@'))
-        
+
         self.java_args = delAtAndSplit(_opts.java_args)
         self.java_args_pfx = sum(map(delAtAndSplit, _opts.java_args_pfx), [])
         self.java_args_sfx = sum(map(delAtAndSplit, _opts.java_args_sfx), [])
-        
+
         # Prepend the -d64 VM option only if the java command supports it
         try:
             output = subprocess.check_output([self.java, '-d64', '-version'], stderr=subprocess.STDOUT)
@@ -694,17 +770,18 @@
             except subprocess.CalledProcessError as e:
                 print e.output
                 abort(e.returncode)
-        
+
         output = output.split()
         assert output[1] == 'version'
         self.version = output[2].strip('"')
-        
-        if self.debug:
-            self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000']
+        self.javaCompliance = JavaCompliance(self.version)
+
+        if self.debug_port is not None:
+            self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(self.debug_port)]
 
     def format_cmd(self, args):
         return [self.java] + self.java_args_pfx + self.java_args + self.java_args_sfx + args
-    
+
 def check_get_env(key):
     """
     Gets an environment variable, aborting with a useful message if it is not set.
@@ -725,7 +802,7 @@
     """
     Write a message to the console.
     All script output goes through this method thus allowing a subclass
-    to redirect it. 
+    to redirect it.
     """
     if msg is None:
         print
@@ -740,7 +817,7 @@
         else:
             cp.append(part)
     return os.pathsep.join(cp)
-    
+
 def expand_project_in_args(args):
     for i in range(len(args)):
         if args[i] == '-cp' or args[i] == '-classpath':
@@ -765,7 +842,7 @@
             abort('Property contains an undefined environment variable: ' + value)
         return result
 
-           
+
 def abort(codeOrMessage):
     """
     Aborts the program with a SystemExit exception.
@@ -773,7 +850,7 @@
     if it is None, the exit status is zero; if it has another type (such as a string),
     the object's value is printed and the exit status is one.
     """
-    
+
     #import traceback
     #traceback.print_stack()
     currentSubprocess = _currentSubprocess
@@ -783,7 +860,7 @@
             p.kill()
         else:
             _kill_process_group(p.pid)
-    
+
     raise SystemExit(codeOrMessage)
 
 def download(path, urls, verbose=False):
@@ -795,23 +872,23 @@
     d = dirname(path)
     if d != '' and not exists(d):
         os.makedirs(d)
-        
+
     # Try it with the Java tool first since it can show a progress counter
     myDir = dirname(__file__)
-    
+
     javaSource = join(myDir, 'URLConnectionDownload.java')
     javaClass = join(myDir, 'URLConnectionDownload.class')
     if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource):
         subprocess.check_call([java().javac, '-d', myDir, javaSource])
     if run([java().java, '-cp', myDir, 'URLConnectionDownload', path] + urls) == 0:
         return
-        
+
     def url_open(url):
         userAgent = 'Mozilla/5.0 (compatible)'
         headers = { 'User-Agent' : userAgent }
         req = urllib2.Request(url, headers=headers)
         return urllib2.urlopen(req);
-        
+
     for url in urls:
         try:
             if (verbose):
@@ -824,7 +901,7 @@
                 with contextlib.closing(url_open(url)) as f:
                     data = f.read()
                     zipdata = StringIO.StringIO(f.read())
-            
+
                 zf = zipfile.ZipFile(zipdata, 'r')
                 data = zf.read(entry)
                 with open(path, 'wb') as f:
@@ -839,10 +916,10 @@
             log('Error reading from ' + url + ': ' + str(e))
         except zipfile.BadZipfile as e:
             log('Error in zip file downloaded from ' + url + ': ' + str(e))
-            
+
     abort('Could not download to ' + path + ' from any of the following URLs:\n\n    ' +
               '\n    '.join(urls) + '\n\nPlease use a web browser to do the download manually')
-            
+
 def update_file(path, content):
     """
     Updates a file with some given content if the content differs from what's in
@@ -854,44 +931,47 @@
         if existed:
             with open(path, 'rb') as f:
                 old = f.read()
-        
+
         if old == content:
             return False
-            
+
         with open(path, 'wb') as f:
             f.write(content)
-            
+
         log(('modified ' if existed else 'created ') + path)
         return True;
     except IOError as e:
         abort('Error while writing to ' + path + ': ' + str(e));
 
 # Builtin commands
-            
+
 def build(args, parser=None):
     """compile the Java and C sources, linking the latter
 
     Compile all the Java source code using the appropriate compilers
     and linkers for the various source code types."""
-    
+
     suppliedParser = parser is not None
     if not suppliedParser:
         parser = ArgumentParser(prog='mx build')
-    
+
+    javaCompliance = java().javaCompliance
+
     parser = parser if parser is not None else ArgumentParser(prog='mx build')
     parser.add_argument('-f', action='store_true', dest='force', help='force compilation even if class files are up to date')
     parser.add_argument('-c', action='store_true', dest='clean', help='removes existing build output')
-    parser.add_argument('--source', dest='compliance', help='Java compliance level', default='1.6')
+    parser.add_argument('--source', dest='compliance', help='Java compliance level', default=str(javaCompliance))
     parser.add_argument('--Wapi', action='store_true', dest='warnAPI', help='show warnings about using internal APIs')
+    parser.add_argument('--projects', action='store', help='comma separated projects to build (omit to build all projects)')
     parser.add_argument('--no-java', action='store_false', dest='java', help='do not build Java projects')
     parser.add_argument('--no-native', action='store_false', dest='native', help='do not build native projects')
     parser.add_argument('--jdt', help='Eclipse installation or path to ecj.jar for using the Eclipse batch compiler instead of javac', metavar='<path>')
-    
+
     if suppliedParser:
         parser.add_argument('remainder', nargs=REMAINDER, metavar='...')
 
     args = parser.parse_args(args)
-    
+
     jdtJar = None
     if args.jdt is not None:
         if args.jdt.endswith('.jar'):
@@ -903,15 +983,19 @@
                 jdtJar = join(plugins, sorted(choices, reverse=True)[0])
 
     built = set()
-    for p in sorted_deps():
-        
+
+    projects = None
+    if args.projects is not None:
+        projects = args.projects.split(',')
+
+    for p in sorted_deps(projects):
         if p.native:
             if args.native:
                 log('Calling GNU make {0}...'.format(p.dir))
-    
+
                 if args.clean:
                     run([gmake_cmd(), 'clean'], cwd=p.dir)
-                    
+
                 run([gmake_cmd()], cwd=p.dir)
                 built.add(p.name)
             continue
@@ -919,7 +1003,12 @@
             if not args.java:
                 continue
 
-        
+        # skip building this Java project if its Java compliance level is "higher" than the configured JDK
+        if javaCompliance < p.javaCompliance:
+            log('Excluding {0} from build (Java compliance level {1} required)'.format(p.name, p.javaCompliance))
+            continue
+
+
         outputDir = p.output_dir()
         if exists(outputDir):
             if args.clean:
@@ -936,31 +1025,63 @@
             for dep in p.all_deps([], False):
                 if dep.name in built:
                     mustBuild = True
-            
+
+        jasminAvailable = None
         javafilelist = []
         for sourceDir in sourceDirs:
             for root, _, files in os.walk(sourceDir):
                 javafiles = [join(root, name) for name in files if name.endswith('.java') and name != 'package-info.java']
                 javafilelist += javafiles
-                
-                # Copy all non Java resources
+
+                # Copy all non Java resources or assemble Jasmin files
                 nonjavafilelist = [join(root, name) for name in files if not name.endswith('.java')]
                 for src in nonjavafilelist:
-                    dst = join(outputDir, src[len(sourceDir) + 1:])
-                    if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) != os.path.getmtime(src)):
-                        shutil.copyfile(src, dst)
-                
+                    if src.endswith('.jasm'):
+                        className = None
+                        with open(src) as f:
+                            for line in f:
+                                if line.startswith('.class '):
+                                    className = line.split()[-1]
+                                    break
+
+                        if className is not None:
+                            jasminOutputDir = p.jasmin_output_dir()
+                            classFile = join(jasminOutputDir, className.replace('/', os.sep) + '.class')
+                            if exists(dirname(classFile)) and (not exists(classFile) or os.path.getmtime(classFile) < os.path.getmtime(src)):
+                                if jasminAvailable is None:
+                                    try:
+                                        with open(os.devnull) as devnull:
+                                            subprocess.call('jasmin', stdout=devnull, stderr=subprocess.STDOUT)
+                                        jasminAvailable = True
+                                    except OSError as e:
+                                        jasminAvailable = False
+
+                                if jasminAvailable:
+                                    log('Assembling Jasmin file ' + src)
+                                    run(['jasmin', '-d', jasminOutputDir, src])
+                                else:
+                                    log('The jasmin executable could not be found - skipping ' + src)
+                                    with file(classFile, 'a'):
+                                        os.utime(classFile, None)
+
+                        else:
+                            log('could not file .class directive in Jasmin source: ' + src)
+                    else:
+                        dst = join(outputDir, src[len(sourceDir) + 1:])
+                        if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) != os.path.getmtime(src)):
+                            shutil.copyfile(src, dst)
+
                 if not mustBuild:
                     for javafile in javafiles:
                         classfile = outputDir + javafile[len(sourceDir):-len('java')] + 'class'
                         if not exists(classfile) or os.path.getmtime(javafile) > os.path.getmtime(classfile):
                             mustBuild = True
                             break
-                
+
         if not mustBuild:
             log('[all class files for {0} are up to date - skipping]'.format(p.name))
             continue
-            
+
         if len(javafilelist) == 0:
             log('[no Java sources for {0} - skipping]'.format(p.name))
             continue
@@ -971,7 +1092,7 @@
         argfile = open(argfileName, 'wb')
         argfile.write('\n'.join(javafilelist))
         argfile.close()
-        
+
         try:
             if jdtJar is None:
                 log('Compiling Java sources for {0} with javac...'.format(p.name))
@@ -981,11 +1102,11 @@
                         """
                         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
@@ -994,7 +1115,7 @@
                             else:
                                 log(line.rstrip())
                     errFilt=Filter().eat
-                    
+
                 run([java().javac, '-g', '-J-Xmx1g', '-source', args.compliance, '-classpath', cp, '-d', outputDir, '@' + argfile.name], err=errFilt)
             else:
                 log('Compiling Java sources for {0} with JDT...'.format(p.name))
@@ -1009,7 +1130,7 @@
                          '-d', outputDir, '@' + argfile.name])
         finally:
             os.remove(argfileName)
-                    
+
     if suppliedParser:
         return args
     return None
@@ -1018,7 +1139,7 @@
     """process all project files to canonicalize the dependencies
 
     The exit code of this command reflects how many files were updated."""
-    
+
     changedFiles = 0
     for s in suites():
         projectsFile = join(s.dir, 'mx', 'projects')
@@ -1039,7 +1160,7 @@
         if update_file(projectsFile, content):
             changedFiles += 1
     return changedFiles;
-    
+
 def checkstyle(args):
     """run Checkstyle on the Java sources
 
@@ -1047,16 +1168,16 @@
    produced by Checkstyle result in a non-zero exit code.
 
 If no projects are given, then all Java projects are checked."""
-    
+
     for p in sorted_deps():
         if p.native:
             continue
         sourceDirs = p.source_dirs()
         dotCheckstyle = join(p.dir, '.checkstyle')
-        
+
         if not exists(dotCheckstyle):
             continue
-        
+
         for sourceDir in sourceDirs:
             javafilelist = []
             for root, _, files in os.walk(sourceDir):
@@ -1075,16 +1196,16 @@
                         break
             else:
                 mustCheck = True
-            
+
             if not mustCheck:
                 log('[all Java sources in {0} already checked - skipping]'.format(sourceDir))
                 continue
 
-            if exists(timestampFile):                
+            if exists(timestampFile):
                 os.utime(timestampFile, None)
             else:
                 file(timestampFile, 'a')
-            
+
             dotCheckstyleXML = xml.dom.minidom.parse(dotCheckstyle)
             localCheckConfig = dotCheckstyleXML.getElementsByTagName('local-check-config')[0]
             configLocation = localCheckConfig.getAttribute('location')
@@ -1102,9 +1223,9 @@
             else:
                 log('[unknown Checkstyle configuration type "' + configType + '" in {0} - skipping]'.format(sourceDir))
                 continue
-                
+
             exclude = join(p.dir, '.checkstyle.exclude')
-            
+
             if exists(exclude):
                 with open(exclude) as f:
                     # Convert patterns to OS separators
@@ -1112,15 +1233,16 @@
                 def match(name):
                     for p in patterns:
                         if p in name:
-                            log('excluding: ' + name)
+                            if _opts.verbose:
+                                log('excluding: ' + name)
                             return True
                     return False
-                    
+
                 javafilelist = [name for name in javafilelist if not match(name)]
-            
+
             auditfileName = join(p.dir, 'checkstyleOutput.txt')
             log('Running Checkstyle on {0} using {1}...'.format(sourceDir, config))
-            
+
             try:
 
                 # Checkstyle is unable to read the filenames to process from a file, and the
@@ -1137,7 +1259,7 @@
                             i += 1
                         else:
                             break
-                    
+
                     batch = javafilelist[:i]
                     javafilelist = javafilelist[i:]
                     try:
@@ -1162,13 +1284,13 @@
     """
 
     suppliedParser = parser is not None
-    
+
     parser = parser if suppliedParser else ArgumentParser(prog='mx build');
     parser.add_argument('--no-native', action='store_false', dest='native', help='do not clean native projects')
     parser.add_argument('--no-java', action='store_false', dest='java', help='do not clean Java projects')
 
     args = parser.parse_args(args)
-    
+
     for p in projects():
         if p.native:
             if args.native:
@@ -1179,10 +1301,14 @@
                 if outputDir != '' and exists(outputDir):
                     log('Removing {0}...'.format(outputDir))
                     shutil.rmtree(outputDir)
-                    
+
     if suppliedParser:
         return args
-    
+
+def about(args):
+    """show the 'man page' for mx"""
+    print __doc__
+
 def help_(args):
     """show help for a given command
 
@@ -1192,11 +1318,11 @@
     if len(args) == 0:
         _argParser.print_help()
         return
-    
+
     name = args[0]
     if not commands.has_key(name):
         _argParser.error('unknown command: ' + name)
-    
+
     value = commands[name]
     (func, usage) = value[:2]
     doc = func.__doc__
@@ -1213,7 +1339,7 @@
 
 def projectgraph(args, suite=None):
     """create dot graph for project structure ("mx projectgraph | dot -Tpdf -oprojects.pdf")"""
-    
+
     print 'digraph projects {'
     print 'rankdir=BT;'
     print 'node [shape=rect];'
@@ -1227,19 +1353,28 @@
 
     if suite is None:
         suite = _mainSuite
-        
+
     def println(out, obj):
         out.write(str(obj) + '\n')
-        
+
     for p in projects():
-        if p.native:
-            continue
-        
         if not exists(p.dir):
             os.makedirs(p.dir)
 
+        if p.native:
+            eclipseNativeSettingsDir = join(suite.dir, 'mx', 'eclipse-native-settings')
+            if exists(eclipseNativeSettingsDir):
+                for name in os.listdir(eclipseNativeSettingsDir):
+                    path = join(eclipseNativeSettingsDir, name)
+                    if isfile(path):
+                        with open(join(eclipseNativeSettingsDir, name)) as f:
+                            content = f.read()
+                        content = content.replace('${javaHome}', java().jdk)
+                        update_file(join(p.dir, name), content)
+            continue
+
         out = StringIO.StringIO()
-        
+
         println(out, '<?xml version="1.0" encoding="UTF-8"?>')
         println(out, '<classpath>')
         for src in p.srcDirs:
@@ -1247,14 +1382,14 @@
             if not exists(srcDir):
                 os.mkdir(srcDir)
             println(out, '\t<classpathentry kind="src" path="' + src + '"/>')
-    
+
         # Every Java program depends on the JRE
         println(out, '\t<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>')
-        
+
         for dep in p.all_deps([], True):
             if dep == p:
                 continue;
-            
+
             if dep.isLibrary():
                 if hasattr(dep, 'eclipse.container'):
                     println(out, '\t<classpathentry exported="true" kind="con" path="' + getattr(dep, 'eclipse.container') + '"/>')
@@ -1267,10 +1402,11 @@
                         if isabs(path):
                             println(out, '\t<classpathentry exported="true" kind="lib" path="' + path + '"/>')
                         else:
-                            println(out, '\t<classpathentry exported="true" kind="lib" path="' + join(suite.dir, path) + '"/>')
+                            projRelPath = os.path.relpath(join(suite.dir, path), p.dir)
+                            println(out, '\t<classpathentry exported="true" kind="lib" path="' + projRelPath + '"/>')
             else:
                 println(out, '\t<classpathentry combineaccessrules="false" exported="true" kind="src" path="/' + dep.name + '"/>')
-                        
+
         println(out, '\t<classpathentry kind="output" path="' + getattr(p, 'eclipse.output', 'bin') + '"/>')
         println(out, '</classpath>')
         update_file(join(p.dir, '.classpath'), out.getvalue())
@@ -1279,7 +1415,7 @@
         csConfig = join(project(p.checkstyleProj).dir, '.checkstyle_checks.xml')
         if exists(csConfig):
             out = StringIO.StringIO()
-            
+
             dotCheckstyle = join(p.dir, ".checkstyle")
             checkstyleConfigPath = '/' + p.checkstyleProj + '/.checkstyle_checks.xml'
             println(out, '<?xml version="1.0" encoding="UTF-8"?>')
@@ -1305,14 +1441,14 @@
                             assert isdir(exclDir), 'excluded source directory listed in ' + exclude + ' does not exist or is not a directory: ' + exclDir
                         println(out, '\t\t<filter-data value="' + line + '"/>')
                 println(out, '\t</filter>')
-                        
+
             println(out, '</fileset-config>')
             update_file(dotCheckstyle, out.getvalue())
             out.close()
-        
+
 
         out = StringIO.StringIO()
-        
+
         println(out, '<?xml version="1.0" encoding="UTF-8"?>')
         println(out, '<projectDescription>')
         println(out, '\t<name>' + p.name + '</name>')
@@ -1353,6 +1489,7 @@
                 if isfile(path):
                     with open(join(eclipseSettingsDir, name)) as f:
                         content = f.read()
+                    content = content.replace('${javaCompliance}', str(p.javaCompliance))
                     update_file(join(settingsDir, name), content)
 
 def netbeansinit(args, suite=None):
@@ -1363,17 +1500,17 @@
 
     def println(out, obj):
         out.write(str(obj) + '\n')
-        
+
     updated = False
     for p in projects():
         if p.native:
             continue
-        
+
         if not exists(join(p.dir, 'nbproject')):
             os.makedirs(join(p.dir, 'nbproject'))
 
         out = StringIO.StringIO()
-        
+
         println(out, '<?xml version="1.0" encoding="UTF-8"?>')
         println(out, '<project name="' + p.name + '" default="default" basedir=".">')
         println(out, '\t<description>Builds, tests, and runs the project ' + p.name + '.</description>')
@@ -1381,7 +1518,7 @@
         println(out, '</project>')
         updated = update_file(join(p.dir, 'build.xml'), out.getvalue()) or updated
         out.close()
-        
+
         out = StringIO.StringIO()
         println(out, '<?xml version="1.0" encoding="UTF-8"?>')
         println(out, '<project xmlns="http://www.netbeans.org/ns/project/1">')
@@ -1397,18 +1534,18 @@
         println(out, '                <root id="test.src.dir"/>')
         println(out, '            </test-roots>')
         println(out, '        </data>')
-        
+
         firstDep = True
         for dep in p.all_deps([], True):
             if dep == p:
                 continue;
-            
+
             if not dep.isLibrary():
                 n = dep.name.replace('.', '_')
                 if firstDep:
                     println(out, '        <references xmlns="http://www.netbeans.org/ns/ant-project-references/1">')
                     firstDep = False
-                    
+
                 println(out, '            <reference>')
                 println(out, '                <foreign-project>' + n + '</foreign-project>')
                 println(out, '                <artifact-type>jar</artifact-type>')
@@ -1417,19 +1554,19 @@
                 println(out, '                <clean-target>clean</clean-target>')
                 println(out, '                <id>jar</id>')
                 println(out, '            </reference>')
-            
+
         if not firstDep:
             println(out, '        </references>')
-            
+
         println(out, '    </configuration>')
         println(out, '</project>')
         updated = update_file(join(p.dir, 'nbproject', 'project.xml'), out.getvalue()) or updated
         out.close()
-        
+
         out = StringIO.StringIO()
-        
+
         jdkPlatform = 'JDK_' + java().version
-        
+
         content = """
 annotation.processing.enabled=false
 annotation.processing.enabled.in.editor=false
@@ -1517,12 +1654,12 @@
                 mainSrc = False
             else:
                 println(out, 'src.' + src + '.dir=${' + ref + '}')
-            
-        javacClasspath = []    
+
+        javacClasspath = []
         for dep in p.all_deps([], True):
             if dep == p:
                 continue;
-            
+
             if dep.isLibrary():
                 if not dep.mustExist:
                     continue
@@ -1531,22 +1668,22 @@
                     path = path.replace('\\', '\\\\')
                 ref = 'file.reference.' + dep.name + '-bin'
                 println(out, ref + '=' + path)
-                    
+
             else:
                 n = dep.name.replace('.', '_')
                 relDepPath = os.path.relpath(dep.dir, p.dir).replace(os.sep, '/')
                 ref = 'reference.' + n + '.jar'
                 println(out, 'project.' + n + '=' + relDepPath)
                 println(out, ref + '=${project.' + n + '}/dist/' + dep.name + '.jar')
-                
+
             javacClasspath.append('${' + ref + '}')
-            
+
         println(out, 'javac.classpath=\\\n    ' + (os.pathsep + '\\\n    ').join(javacClasspath))
-        
+
 
         updated = update_file(join(p.dir, 'nbproject', 'project.properties'), out.getvalue()) or updated
         out.close()
-    
+
     if updated:
         log('If using NetBeans:')
         log('  1. Ensure that a platform named "JDK ' + java().version + '" is defined (Tools -> Java Platforms)')
@@ -1554,21 +1691,21 @@
 
 def ideclean(args, suite=None):
     """remove all Eclipse and NetBeans project configurations"""
-    
+
     def rm(path):
         if exists(path):
             os.remove(path)
-    
+
     for p in projects():
         if p.native:
             continue
-        
+
         shutil.rmtree(join(p.dir, '.settings'), ignore_errors=True)
         shutil.rmtree(join(p.dir, 'nbproject'), ignore_errors=True)
         rm(join(p.dir, '.classpath'))
         rm(join(p.dir, '.project'))
         rm(join(p.dir, 'build.xml'))
-        
+
 def ideinit(args, suite=None):
     """(re)generate Eclipse and NetBeans project configurations"""
     eclipseinit(args, suite)
@@ -1580,7 +1717,7 @@
     Run the JDK javap class file disassembler with the following prepended options:
 
         -private -verbose -classpath <path to project classes>"""
-        
+
     javap = java().javap
     if not exists(javap):
         abort('The javap executable does not exists: ' + javap)
@@ -1602,13 +1739,14 @@
     """
     assert _argParser is not None
     _argParser.add_argument(*args, **kwargs)
-    
+
 # Table of commands in alphabetical order.
 # Keys are command names, value are lists: [<function>, <usage msg>, <format args to doc string of function>...]
 # If any of the format args are instances of Callable, then they are called with an 'env' are before being
-# used in the call to str.format().  
+# used in the call to str.format().
 # Extensions should update this table directly
 commands = {
+    'about': [about, ''],
     'build': [build, '[options]'],
     'checkstyle': [checkstyle, ''],
     'canonicalizeprojects': [canonicalizeprojects, ''],
@@ -1630,26 +1768,26 @@
     if exists(cwdMxDir) and isdir(cwdMxDir):
         global _mainSuite
         _mainSuite = _loadSuite(os.getcwd(), True)
-            
+
     opts, commandAndArgs = _argParser._parse_cmd_line()
-    
+
     global _opts, _java
     _opts = opts
     _java = JavaConfig(opts)
-    
+
     for s in suites():
         s._post_init(opts)
-    
+
     if len(commandAndArgs) == 0:
         _argParser.print_help()
         return
-    
+
     command = commandAndArgs[0]
     command_args = commandAndArgs[1:]
-    
+
     if not commands.has_key(command):
         abort('mx: unknown command \'{0}\'\n{1}use "mx help" for more options'.format(command, _format_commands()))
-        
+
     c, _ = commands[command][:2]
     def term_handler(signum, frame):
         abort(1)