changeset 3201:38792f959479

Merge
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Fri, 08 Jul 2011 15:00:16 +0200
parents 536b02e3cd2b (current diff) 3d68684b7161 (diff)
children 9352a9c26095
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NotInstanceOf.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java graal/com.oracle.max.graal.runtime/README.txt
diffstat 116 files changed, 4218 insertions(+), 1502 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri Jul 08 14:49:01 2011 +0200
+++ b/.hgignore	Fri Jul 08 15:00:16 2011 +0200
@@ -20,6 +20,7 @@
 ^Test.java$
 ^diff1.txt$
 ^diff2.txt$
+^examples.jar$
 ^test.xml$
 java\.hprof\.txt$
 /nbproject/private/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/create_examples.xml	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project default="create_run_jar" name="Create Runnable Jar for Project com.oracle.max.graal.examples">
+    <!--this file was created by Eclipse Runnable JAR Export Wizard-->
+    <!--ANT 1.7 is required                                        -->
+    <target name="create_run_jar">
+        <jar destfile="./examples.jar" filesetmanifest="mergewithoutmain">
+            <manifest>
+                <attribute name="Main-Class" value="com.oracle.max.graal.examples.Main"/>
+                <attribute name="Class-Path" value="."/>
+            </manifest>
+            <fileset dir="./graal/com.oracle.max.graal.examples/bin"/>
+        </jar>
+    </target>
+</project>
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Fri Jul 08 15:00:16 2011 +0200
@@ -30,7 +30,7 @@
 import com.oracle.max.graal.compiler.asm.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.gen.LIRGenerator.*;
+import com.oracle.max.graal.compiler.gen.LIRGenerator.DeoptimizationStub;
 import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.observer.*;
@@ -239,8 +239,8 @@
 
             lirGenerator = compiler.backend.newLIRGenerator(this);
 
-            for (LIRBlock begin : hir.linearScanOrder()) {
-                lirGenerator.doBlock(begin);
+            for (LIRBlock b : hir.linearScanOrder()) {
+                lirGenerator.doBlock(b);
             }
 
             if (GraalOptions.Time) {
@@ -258,7 +258,7 @@
     private CiTargetMethod emitCode() {
         if (GraalOptions.GenLIR && GraalOptions.GenCode) {
             final LIRAssembler lirAssembler = compiler.backend.newLIRAssembler(this);
-            lirAssembler.emitCode(hir.linearScanOrder());
+            lirAssembler.emitCode(hir.codeEmittingOrder());
 
             // generate code for slow cases
             lirAssembler.emitLocalStubs();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Fri Jul 08 15:00:16 2011 +0200
@@ -85,6 +85,8 @@
     public static boolean PrintDOTGraphToPdf                 = ____;
     public static boolean OmitDOTFrameStates                 = ____;
 
+    public static boolean Extend                             = ____;
+
     // Ideal graph visualizer output settings
     public static boolean Plot                               = ____;
     public static boolean PlotOnError                        = ____;
@@ -129,6 +131,7 @@
     public static boolean UseBranchPrediction                = true;
     public static boolean UseExceptionProbability            = ____;
     public static int     MatureInvocationCount              = 100;
+    public static boolean GenSafepoints                      = true;
 
     public static boolean UseConstDirectCall                 = ____;
 
@@ -153,8 +156,11 @@
     public static boolean CommentedAssembly                  = ____;
     public static boolean PrintLIRWithAssembly               = ____;
 
+    public static boolean OptReadElimination                 = ____;
     public static boolean OptGVN                             = ____;
     public static boolean OptCanonicalizer                   = true;
     public static boolean OptLoops                           = ____;
+    public static boolean OptOptimisticSchedule              = ____;
+    public static boolean OptReorderLoops                    = ____;
     public static boolean LoopPeeling                        = ____;
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java	Fri Jul 08 15:00:16 2011 +0200
@@ -42,7 +42,7 @@
      */
     public static void optimize(IR ir) {
         ControlFlowOptimizer optimizer = new ControlFlowOptimizer(ir);
-        List<LIRBlock> code = ir.linearScanOrder();
+        List<LIRBlock> code = ir.codeEmittingOrder();
         optimizer.reorderShortLoops(code);
         optimizer.deleteEmptyBlocks(code);
         optimizer.deleteUnnecessaryJumps(code);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Fri Jul 08 15:00:16 2011 +0200
@@ -26,20 +26,23 @@
 import static java.lang.reflect.Modifier.*;
 
 import java.util.*;
+import java.util.Map.Entry;
 
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.alloc.Interval.*;
+import com.oracle.max.graal.compiler.alloc.Interval.RegisterBinding;
+import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority;
+import com.oracle.max.graal.compiler.alloc.Interval.SpillState;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.*;
+import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
 import com.oracle.max.graal.compiler.observer.*;
-import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeField;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.value.*;
-import com.oracle.max.graal.compiler.value.FrameState.*;
+import com.oracle.max.graal.compiler.value.FrameState.ValueProcedure;
+import com.oracle.max.graal.extensions.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -634,6 +637,7 @@
                 // Add uses of live locals from interpreter's point of view for proper debug information generation
                 LIRDebugInfo info = op.info;
                 if (info != null) {
+                    assert info.state != null;
                     info.state.forEachLiveStateValue(new ValueProcedure() {
                         public void doValue(Value value) {
                             CiValue operand = value.operand();
@@ -1837,117 +1841,183 @@
         }
     }
 
-    CiValue toCiValue(int opId, Value value) {
-        if (value instanceof VirtualObject) {
-            return toCiVirtualObject(opId, (VirtualObject) value);
-        } else if (value != null && value.operand() != CiValue.IllegalValue) {
-            CiValue operand = value.operand();
-            Constant con = null;
-            if (value instanceof Constant) {
-                con = (Constant) value;
-            }
-
-            assert con == null || operand.isVariable() || operand.isConstant() || operand.isIllegal() : "Constant instructions have only constant operands (or illegal if constant is optimized away)";
+    public static ThreadLocal<ServiceLoader<FrameModifier>> frameModifierLoader = new ThreadLocal<ServiceLoader<FrameModifier>>();
 
-            if (operand.isVariable()) {
-                OperandMode mode = OperandMode.Input;
-                LIRBlock block = blockForId(opId);
-                if (block.numberOfSux() == 1 && opId == block.lastLirInstructionId()) {
-                    // generating debug information for the last instruction of a block.
-                    // if this instruction is a branch, spill moves are inserted before this branch
-                    // and so the wrong operand would be returned (spill moves at block boundaries are not
-                    // considered in the live ranges of intervals)
-                    // Solution: use the first opId of the branch target block instead.
-                    final LIRInstruction instr = block.lir().instructionsList().get(block.lir().instructionsList().size() - 1);
-                    if (instr instanceof LIRBranch) {
-                        if (block.liveOut.get(operandNumber(operand))) {
-                            opId = block.suxAt(0).firstLirInstructionId();
-                            mode = OperandMode.Output;
-                        }
-                    }
-                }
+    private CiFrame overrideFrame(CiFrame frame) {
+        ServiceLoader<FrameModifier> serviceLoader = frameModifierLoader.get();
+        if (serviceLoader == null) {
+            serviceLoader = ServiceLoader.load(FrameModifier.class);
+            frameModifierLoader.set(serviceLoader);
+        }
 
-                // Get current location of operand
-                // The operand must be live because debug information is considered when building the intervals
-                // if the interval is not live, colorLirOperand will cause an assert on failure
-                operand = colorLirOperand((CiVariable) operand, opId, mode);
-                assert !hasCall(opId) || operand.isStackSlot() || !isCallerSave(operand) : "cannot have caller-save register operands at calls";
-                return operand;
-            } else if (operand.isRegister()) {
-                assert false : "must not reach here";
-                return operand;
-            } else {
-                assert value instanceof Constant;
-                assert operand.isConstant() : "operand must be constant";
-                return operand;
-            }
-        } else {
-            // return a dummy value because real value not needed
-            return CiValue.IllegalValue;
+        CiFrame result = frame;
+        for (FrameModifier modifier : serviceLoader) {
+            result = modifier.getFrame(compilation.runtime, result);
         }
+        return result;
     }
 
-    private CiVirtualObject toCiVirtualObject(int opId, VirtualObject obj) {
-        RiType type = obj.type();
-        EscapeField[] escapeFields = obj.fields();
-        CiValue[] values = new CiValue[escapeFields.length];
-        int valuesFilled = 0;
+
+    private class DebugFrameBuilder {
+
+        private final FrameState topState;
+        private final int opId;
+        private final BitMap frameRefMap;
+
+        private HashMap<VirtualObject, CiVirtualObject> virtualObjects;
+
+        public DebugFrameBuilder(FrameState topState, int opId, BitMap frameRefMap) {
+            this.topState = topState;
+            this.opId = opId;
+            this.frameRefMap = frameRefMap;
+        }
+
+        private CiValue toCiValue(Value value) {
+            if (value instanceof VirtualObject) {
+                if (virtualObjects == null) {
+                    virtualObjects = new HashMap<VirtualObject, CiVirtualObject>();
+                }
+                VirtualObject obj = (VirtualObject) value;
+                CiVirtualObject ciObj = virtualObjects.get(value);
+                if (ciObj == null) {
+                    ciObj = CiVirtualObject.get(obj.type(), null, value.id());
+                    virtualObjects.put(obj, ciObj);
+                }
+                return ciObj;
+            } else if (value != null && value.operand() != CiValue.IllegalValue) {
+                CiValue operand = value.operand();
+                Constant con = null;
+                if (value instanceof Constant) {
+                    con = (Constant) value;
+                }
+
+                assert con == null || operand.isVariable() || operand.isConstant() || operand.isIllegal() : "Constant instructions have only constant operands (or illegal if constant is optimized away)";
 
-        VirtualObject current = obj;
-        do {
-            boolean found = false;
-            for (int i = 0; i < escapeFields.length; i++) {
-                if (escapeFields[i].representation() == current.field().representation()) {
-                    if (values[i] == null) {
-                        values[i] = toCiValue(opId, current.input());
-                        valuesFilled++;
+                int tempOpId = this.opId;
+                if (operand.isVariable()) {
+                    OperandMode mode = OperandMode.Input;
+                    LIRBlock block = blockForId(tempOpId);
+                    if (block.numberOfSux() == 1 && tempOpId == block.lastLirInstructionId()) {
+                        // generating debug information for the last instruction of a block.
+                        // if this instruction is a branch, spill moves are inserted before this branch
+                        // and so the wrong operand would be returned (spill moves at block boundaries are not
+                        // considered in the live ranges of intervals)
+                        // Solution: use the first opId of the branch target block instead.
+                        final LIRInstruction instr = block.lir().instructionsList().get(block.lir().instructionsList().size() - 1);
+                        if (instr instanceof LIRBranch) {
+                            if (block.liveOut.get(operandNumber(operand))) {
+                                tempOpId = block.suxAt(0).firstLirInstructionId();
+                                mode = OperandMode.Output;
+                            }
+                        }
                     }
-                    found = true;
-                    break;
+
+                    // Get current location of operand
+                    // The operand must be live because debug information is considered when building the intervals
+                    // if the interval is not live, colorLirOperand will cause an assert on failure
+                    operand = colorLirOperand((CiVariable) operand, tempOpId, mode);
+                    assert !hasCall(tempOpId) || operand.isStackSlot() || !isCallerSave(operand) : "cannot have caller-save register operands at calls";
+                    return operand;
+                } else if (operand.isRegister()) {
+                    assert false : "must not reach here";
+                    return operand;
+                } else {
+                    assert value instanceof Constant;
+                    assert operand.isConstant() : "operand must be constant";
+                    return operand;
                 }
+            } else {
+                // return a dummy value because real value not needed
+                return CiValue.IllegalValue;
             }
-            assert found : type + "." + current.field() + " not found";
-            current = current.object();
-        } while (current != null && valuesFilled < values.length);
-
-        for (int i = 0; i < escapeFields.length; i++) {
-            assert values[i] != null : type + "." + escapeFields[i];
         }
 
-        return CiVirtualObject.get(type, values, obj.id());
-    }
+        private CiFrame computeFrameForState(FrameState state) {
+            CiValue[] values = new CiValue[state.valuesSize() + state.locksSize()];
+            int valueIndex = 0;
+
+            for (int i = 0; i < state.valuesSize(); i++) {
+                values[valueIndex++] = toCiValue(state.valueAt(i));
+            }
 
-    CiFrame computeFrameForState(FrameState state, int opId, BitMap frameRefMap) {
-        CiValue[] values = new CiValue[state.valuesSize() + state.locksSize()];
-        int valueIndex = 0;
-
-        for (int i = 0; i < state.valuesSize(); i++) {
-            values[valueIndex++] = toCiValue(opId, state.valueAt(i));
+            for (int i = 0; i < state.locksSize(); i++) {
+                if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
+                    CiStackSlot monitorAddress = frameMap.toMonitorBaseStackAddress(i);
+                    values[valueIndex++] = monitorAddress;
+                    CiStackSlot objectAddress = frameMap.toMonitorObjectStackAddress(i);
+                    frameRefMap.set(objectAddress.index());
+                } else {
+                    Value lock = state.lockAt(i);
+                    if (lock.isConstant() && compilation.runtime.asJavaClass(lock.asConstant()) != null) {
+                        // lock on class for synchronized static method
+                        values[valueIndex++] = lock.asConstant();
+                    } else {
+                        values[valueIndex++] = toCiValue(lock);
+                    }
+                }
+            }
+            CiFrame caller = null;
+            if (state.outerFrameState() != null) {
+                caller = computeFrameForState(state.outerFrameState());
+            }
+            CiFrame frame = new CiFrame(caller, state.method, state.bci, state.rethrowException(), values, state.localsSize(), state.stackSize(), state.locksSize());
+            if (GraalOptions.Extend) {
+                frame = overrideFrame(frame);
+            }
+            return frame;
         }
 
-        for (int i = 0; i < state.locksSize(); i++) {
-            if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
-                CiStackSlot monitorAddress = frameMap.toMonitorBaseStackAddress(i);
-                values[valueIndex++] = monitorAddress;
-                assert frameRefMap != null;
-                CiStackSlot objectAddress = frameMap.toMonitorObjectStackAddress(i);
-//                LIRDebugInfo.setBit(frameRefMap, objectAddress.index());
-                frameRefMap.set(objectAddress.index());
-            } else {
-                Value lock = state.lockAt(i);
-                if (lock.isConstant() && compilation.runtime.asJavaClass(lock.asConstant()) != null) {
-                   // lock on class for synchronized static method
-                   values[valueIndex++] = lock.asConstant();
-                } else {
-                   values[valueIndex++] = toCiValue(opId, lock);
-                }
+        public CiFrame build() {
+            CiFrame frame = computeFrameForState(topState);
+
+            if (virtualObjects != null) {
+                // collect all VirtualObjectField instances:
+                HashMap<VirtualObject, VirtualObjectField> objectStates = new HashMap<VirtualObject, VirtualObjectField>();
+                FrameState current = topState;
+                do {
+                    for (Node n : current.virtualObjectMappings()) {
+                        VirtualObjectField field = (VirtualObjectField) n;
+                        // null states occur for objects with 0 fields
+                        if (field != null && !objectStates.containsKey(field.object())) {
+                            objectStates.put(field.object(), field);
+                        }
+                    }
+                    current = current.outerFrameState();
+                } while (current != null);
+                // fill in the CiVirtualObject values:
+                // during this process new CiVirtualObjects might be discovered, so repeat until no more changes occur.
+                boolean changed;
+                do {
+                    changed = false;
+                    HashMap<VirtualObject, CiVirtualObject> virtualObjectsCopy = new HashMap<VirtualObject, CiVirtualObject>(virtualObjects);
+                    for (Entry<VirtualObject, CiVirtualObject> entry : virtualObjectsCopy.entrySet()) {
+                        if (entry.getValue().values() == null) {
+                            VirtualObject vobj = entry.getKey();
+                            CiValue[] values = new CiValue[vobj.fields().length];
+                            entry.getValue().setValues(values);
+                            if (vobj.fields().length > 0) {
+                                changed = true;
+                                FloatingNode currentField = objectStates.get(vobj);
+                                assert currentField != null;
+                                do {
+                                    if (currentField instanceof VirtualObjectField) {
+                                        int index = ((VirtualObjectField) currentField).index();
+                                        if (values[index] == null) {
+                                            values[index] = toCiValue(((VirtualObjectField) currentField).input());
+                                        }
+                                        currentField = ((VirtualObjectField) currentField).lastState();
+                                    } else {
+                                        assert currentField instanceof Phi : currentField;
+                                        currentField = (FloatingNode) ((Phi) currentField).valueAt(0);
+                                    }
+                                } while (currentField != null);
+                            }
+                        }
+                    }
+                } while (changed);
             }
+            return frame;
         }
-        CiFrame caller = null;
-        if (state.outerFrameState() != null) {
-            caller = computeFrameForState(state.outerFrameState(), opId, frameRefMap);
-        }
-        return new CiFrame(caller, state.method, state.bci, state.rethrowException(), values, state.localsSize(), state.stackSize(), state.locksSize());
     }
 
     private void computeDebugInfo(IntervalWalker iw, LIRInstruction op) {
@@ -1983,7 +2053,7 @@
         if (GraalOptions.TraceLinearScanLevel >= 3) {
             TTY.println("creating debug information at opId %d", opId);
         }
-        return computeFrameForState(state, opId, frameRefMap);
+        return new DebugFrameBuilder(state, opId, frameRefMap).build();
     }
 
     private void assignLocations(List<LIRInstruction> instructions, IntervalWalker iw) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java	Fri Jul 08 15:00:16 2011 +0200
@@ -109,7 +109,7 @@
                 return;
             }
 
-            printer = new IdealGraphPrinter(stream);
+            printer = new IdealGraphPrinter(new BufferedOutputStream(stream));
             if (GraalOptions.OmitDOTFrameStates) {
                 printer.addOmittedClass(FrameState.class);
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Fri Jul 08 15:00:16 2011 +0200
@@ -39,9 +39,11 @@
 import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.compiler.value.FrameState.ValueProcedure;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.bytecode.Bytecodes.MemoryBarriers;
 import com.sun.cri.ci.*;
@@ -239,11 +241,35 @@
             TTY.println("BEGIN Generating LIR for block B" + block.blockID());
         }
 
-        if (block.blockPredecessors().size() > 1) {
+        if (block == ir.startBlock) {
+            XirSnippet prologue = xir.genPrologue(null, compilation.method);
+            if (prologue != null) {
+                emitXir(prologue, null, null, null, false);
+            }
+            FrameState fs = setOperandsForLocals();
+            if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+                TTY.println("STATE CHANGE (setOperandsForLocals)");
+                if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+                    TTY.println(fs.toString());
+                }
+            }
+            lastState = fs;
+        } else if (block.blockPredecessors().size() > 1) {
             if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
                 TTY.println("STATE RESET");
             }
             lastState = null;
+        }  else if (block.blockPredecessors().size() == 1) {
+            LIRBlock pred = block.blockPredecessors().get(0);
+            FrameState fs = pred.lastState();
+            assert fs != null : "block B" + block.blockID() + " pred block B" + pred.blockID();
+            if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+                TTY.println("STATE CHANGE (singlePred)");
+                if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+                    TTY.println(fs.toString());
+                }
+            }
+            lastState = fs;
         }
 
         for (Node instr : block.getInstructions()) {
@@ -442,13 +468,13 @@
     public void visitExceptionObject(ExceptionObject x) {
         XirSnippet snippet = xir.genExceptionObject(site(x));
         emitXir(snippet, x, null, null, true);
-        lastState = lastState.duplicateWithException(lastState.bci, x);
-        if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
-            TTY.println("STATE CHANGE (visitExceptionObject)");
-            if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
-                TTY.println(lastState.toString());
-            }
-        }
+//        lastState = lastState.duplicateWithException(lastState.bci, x);
+//        if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+//            TTY.println("STATE CHANGE (visitExceptionObject)");
+//            if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+//                TTY.println(lastState.toString());
+//            }
+//        }
     }
 
     @Override
@@ -478,12 +504,14 @@
     }
 
     public void emitBooleanBranch(Node node, LIRBlock trueSuccessor, LIRBlock falseSuccessor, LIRDebugInfo info) {
-        if (node instanceof Compare) {
+        if (node instanceof NegateBooleanNode) {
+            emitBooleanBranch(((NegateBooleanNode) node).value(), falseSuccessor, trueSuccessor, info);
+        } else if (node instanceof Compare) {
             emitCompare((Compare) node, trueSuccessor, falseSuccessor);
         } else if (node instanceof InstanceOf) {
             emitInstanceOf((TypeCheck) node, trueSuccessor, falseSuccessor, info);
-        } else if (node instanceof NotInstanceOf) {
-            emitInstanceOf((TypeCheck) node, falseSuccessor, trueSuccessor, info);
+        } else if (node instanceof Constant) {
+            emitConstantBranch(((Constant) node).asConstant().asBoolean(), trueSuccessor, falseSuccessor, info);
         } else {
             throw Util.unimplemented(node.toString());
         }
@@ -498,6 +526,21 @@
         instr.setFalseSuccessor(falseSuccessor);
     }
 
+
+    public void emitConstantBranch(boolean value, LIRBlock trueSuccessorBlock, LIRBlock falseSuccessorBlock, LIRDebugInfo info) {
+        if (value) {
+            emitConstantBranch(trueSuccessorBlock, info);
+        } else {
+            emitConstantBranch(falseSuccessorBlock, info);
+        }
+    }
+
+    private void emitConstantBranch(LIRBlock block, LIRDebugInfo info) {
+        if (block != null) {
+            lir.jump(block);
+        }
+    }
+
     public void emitCompare(Compare compare, LIRBlock trueSuccessorBlock, LIRBlock falseSuccessorBlock) {
         CiKind kind = compare.x().kind;
 
@@ -580,16 +623,11 @@
     }
 
     protected FrameState stateBeforeInvokeReturn(Invoke invoke) {
-        return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.stateAfter().rethrowException(), invoke.kind);
+        return invoke.stateAfter().duplicateModified(invoke.bci, invoke.stateAfter().rethrowException(), invoke.kind);
     }
 
     protected FrameState stateBeforeInvokeWithArguments(Invoke invoke) {
-        return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.stateAfter().rethrowException(), invoke.kind, invoke.arguments().toArray(new Value[0]));
-    }
-
-    private int getBeforeInvokeBci(Invoke invoke) {
-        // Cannot calculate BCI, because the invoke can have changed from e.g. invokeinterface to invokespecial because of optimizations.
-        return invoke.bci;
+        return invoke.stateAfter().duplicateModified(invoke.bci, invoke.stateAfter().rethrowException(), invoke.kind, invoke.arguments().toArray(new Value[0]));
     }
 
     @Override
@@ -745,7 +783,7 @@
         for (Node n : fixedGuard.inputs()) {
             if (n != null) {
                 emitGuardComp((BooleanNode) n);
-            }
+    }
         }
     }
 
@@ -763,19 +801,33 @@
             XirSnippet typeCheck = xir.genTypeCheck(site(x), toXirArgument(x.object()), clazz, x.type());
             emitXir(typeCheck, x, info, compilation.method, false);
         } else {
-            FrameState state = lastState;
-            assert state != null : "deoptimize instruction always needs a state";
-
-            if (deoptimizationStubs == null) {
-                deoptimizationStubs = new ArrayList<DeoptimizationStub>();
+            if (comp instanceof Constant && comp.asConstant().asBoolean()) {
+                // Nothing to emit.
+            } else {
+                DeoptimizationStub stub = createDeoptStub();
+                emitBooleanBranch(comp, null, new LIRBlock(stub.label, stub.info), stub.info);
             }
-            DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state);
-            deoptimizationStubs.add(stub);
-
-            emitBooleanBranch(comp, null, new LIRBlock(stub.label, stub.info), stub.info);
         }
     }
 
+    private DeoptimizationStub createDeoptStub() {
+        if (deoptimizationStubs == null) {
+            deoptimizationStubs = new ArrayList<DeoptimizationStub>();
+        }
+
+        FrameState state = lastState;
+        assert state != null : "deoptimize instruction always needs a state";
+        DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state);
+        deoptimizationStubs.add(stub);
+        return stub;
+    }
+
+    public void deoptimizeOn(Condition cond) {
+        DeoptimizationStub stub = createDeoptStub();
+        lir.branch(cond, stub.label, stub.info);
+    }
+
+
     @Override
     public void visitPhi(Phi i) {
         Util.shouldNotReachHere();
@@ -1062,30 +1114,6 @@
         block.setLir(lir);
 
         lir.branchDestination(block.label());
-        if (block == ir.startBlock) {
-            XirSnippet prologue = xir.genPrologue(null, compilation.method);
-            if (prologue != null) {
-                emitXir(prologue, null, null, null, false);
-            }
-            FrameState fs = setOperandsForLocals();
-            if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
-                TTY.println("STATE CHANGE (setOperandsForLocals)");
-                if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
-                    TTY.println(fs.toString());
-                }
-            }
-            lastState = fs;
-        } else if (block.blockPredecessors().size() == 1) {
-            FrameState fs = block.blockPredecessors().get(0).lastState();
-            //assert fs != null : "B" + block.blockID() + ", pred=B" + block.blockPredecessors().get(0).blockID();
-            if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
-                TTY.println("STATE CHANGE (singlePred)");
-                if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
-                    TTY.println(fs.toString());
-                }
-            }
-            lastState = fs;
-        }
     }
 
     /**
@@ -1097,7 +1125,7 @@
      * @return the operand that is guaranteed to be a stack location when it is
      *         initially defined a by move from {@code value}
      */
-    CiValue forceToSpill(CiValue value, CiKind kind, boolean mustStayOnStack) {
+    public CiValue forceToSpill(CiValue value, CiKind kind, boolean mustStayOnStack) {
         assert value.isLegal() : "value should not be illegal";
         assert kind.jvmSlots == value.kind.jvmSlots : "size mismatch";
         if (!value.isVariableOrRegister()) {
@@ -1212,7 +1240,7 @@
         }
     }
 
-    protected void arithmeticOpInt(int code, CiValue result, CiValue left, CiValue right, CiValue tmp) {
+    public void arithmeticOpInt(int code, CiValue result, CiValue left, CiValue right, CiValue tmp) {
         CiValue leftOp = left;
 
         if (isTwoOperand && leftOp != result) {
@@ -1252,7 +1280,7 @@
         }
     }
 
-    protected void arithmeticOpLong(int code, CiValue result, CiValue left, CiValue right) {
+    public void arithmeticOpLong(int code, CiValue result, CiValue left, CiValue right) {
         CiValue leftOp = left;
 
         if (isTwoOperand && leftOp != result) {
@@ -1487,6 +1515,9 @@
     public void visitLoopEnd(LoopEnd x) {
         setNoResult(x);
         moveToPhi(x.loopBegin(), x);
+        if (GraalOptions.GenSafepoints) {
+            xir.genSafepoint(site(x));
+        }
         lir.jump(getLIRBlock(x.loopBegin()));
     }
 
@@ -1497,7 +1528,7 @@
         int nextSuccIndex = merge.phiPredecessorIndex(pred);
         PhiResolver resolver = new PhiResolver(this);
         for (Phi phi : merge.phis()) {
-            if (!phi.isDead()) {
+            if (phi.type() == PhiType.Value) {
                 Value curVal = phi.valueAt(nextSuccIndex);
                 if (curVal != null && curVal != phi) {
                     if (curVal instanceof Phi) {
@@ -1559,7 +1590,7 @@
     }
 
     private CiValue operandForPhi(Phi phi) {
-        assert !phi.isDead() : "dead phi: " + phi.id();
+        assert phi.type() == PhiType.Value : "wrong phi type: " + phi.id();
         if (phi.operand().isIllegal()) {
             // allocate a variable for this phi
             createResultVariable(phi);
@@ -1581,7 +1612,7 @@
         x.clearOperand();
     }
 
-    protected CiValue setResult(Value x, CiVariable operand) {
+    public CiValue setResult(Value x, CiVariable operand) {
         x.setOperand(operand);
         if (GraalOptions.DetailedAsserts) {
             operands.recordResult(operand, x);
@@ -1615,57 +1646,25 @@
         }
     }
 
-    protected void walkState(Node x, FrameState state) {
+    protected void walkState(final Node x, FrameState state) {
         if (state == null) {
             return;
         }
 
-        walkState(x, state.outerFrameState());
-
-        for (int index = 0; index < state.stackSize(); index++) {
-            Value value = state.stackAt(index);
-            if (value != x) {
-                walkStateValue(value);
-            }
-        }
-        for (int index = 0; index < state.localsSize(); index++) {
-            final Value value = state.localAt(index);
-            if (value != null) {
-                if (!(value instanceof Phi && ((Phi) value).isDead())) {
-                    walkStateValue(value);
+        state.forEachLiveStateValue(new ValueProcedure() {
+            public void doValue(Value value) {
+                if (value == x) {
+                    // nothing to do, will be visited shortly
+                } else if (value instanceof Phi && ((Phi) value).type() == PhiType.Value) {
+                    // phi's are special
+                    operandForPhi((Phi) value);
+                } else if (value.operand().isIllegal()) {
+                    // instruction doesn't have an operand yet
+                    CiValue operand = makeOperand(value);
+                    assert operand.isLegal() : "must be evaluated now";
                 }
             }
-        }
-    }
-
-    private void walkStateValue(Value value) {
-        if (value != null) {
-            if (value instanceof VirtualObject) {
-                walkVirtualObject((VirtualObject) value);
-            } else if (value instanceof Phi && !((Phi) value).isDead()) {
-                // phi's are special
-                operandForPhi((Phi) value);
-            } else if (value.operand().isIllegal()) {
-                // instruction doesn't have an operand yet
-                CiValue operand = makeOperand(value);
-                assert operand.isLegal() : "must be evaluated now";
-            }
-        }
-    }
-
-    private void walkVirtualObject(VirtualObject value) {
-        if (value.input() instanceof Phi) {
-            assert !((Phi) value.input()).isDead();
-        }
-        HashSet<Object> fields = new HashSet<Object>();
-        VirtualObject obj = value;
-        do {
-            if (!fields.contains(obj.field().representation())) {
-                fields.add(obj.field().representation());
-                walkStateValue(obj.input());
-            }
-            obj = obj.object();
-        } while (obj != null);
+        });
     }
 
     protected LIRDebugInfo stateFor(Value x) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java	Fri Jul 08 15:00:16 2011 +0200
@@ -62,9 +62,6 @@
         } else if (visited.isMarked(phi)) {
             // break cycles in phis
             return phi;
-        } else if (phi.isDead()) {
-            // don't bother with illegals
-            return phi;
         } else {
             // attempt to simplify the phi by recursively simplifying its operands
             visited.mark(phi);
@@ -74,20 +71,20 @@
             for (int i = 0; i < max; i++) {
                 Value oldInstr = phi.valueAt(i);
 
-                if (oldInstr == null || (oldInstr instanceof Phi && ((Phi) oldInstr).isDead())) {
+                if (oldInstr == null) {
                     // if one operand is illegal, make the entire phi illegal
-                    phi.makeDead();
                     visited.clear(phi);
-                    return phi;
+                    phi.replaceAndDelete(null);
+                    return null;
                 }
 
                 Value newInstr = simplify(oldInstr);
 
-                if (newInstr == null || (newInstr instanceof Phi && ((Phi) newInstr).isDead())) {
+                if (newInstr == null) {
                     // if the subst instruction is illegal, make the entire phi illegal
-                    phi.makeDead();
                     visited.clear(phi);
-                    return phi;
+                    phi.replaceAndDelete(null);
+                    return null;
                 }
 
                 // attempt to simplify this operand
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java	Fri Jul 08 15:00:16 2011 +0200
@@ -126,7 +126,7 @@
         final HashSet<Block> successors = new LinkedHashSet<Block>();
         private boolean visited;
         private boolean active;
-        private int loops;
+        private long loops;
     }
 
     public static class ExceptionBlock  extends Block {
@@ -485,7 +485,7 @@
     }
 
     private void computeBlockOrder() {
-        int loop = computeBlockOrder(blockMap[0]);
+        long loop = computeBlockOrder(blockMap[0]);
 
         if (loop != 0) {
             // There is a path from a loop end to the method entry that does not pass the loop header.
@@ -501,7 +501,7 @@
     /**
      * The next available loop number.
      */
-    private int nextLoop = 0;
+    private int nextLoop;
 
     /**
      * Mark the block as a loop header, using the next available loop number.
@@ -516,17 +516,17 @@
                 // Don't compile such methods for now, until we see a concrete case that allows checking for correctness.
                 throw new CiBailout("Loop formed by an exception handler");
             }
-            if (nextLoop >= Integer.SIZE) {
+            if (nextLoop >= Long.SIZE) {
                 // This restriction can be removed by using a fall-back to a BitSet in case we have more than 32 loops
                 // Don't compile such methods for now, until we see a concrete case that allows checking for correctness.
                 throw new CiBailout("Too many loops in method");
             }
 
             assert block.loops == 0;
-            block.loops = 1 << nextLoop;
+            block.loops = (long) 1 << (long) nextLoop;
             nextLoop++;
         }
-        assert Integer.bitCount(block.loops) == 1;
+        assert Long.bitCount(block.loops) == 1;
     }
 
     /**
@@ -534,7 +534,7 @@
      * visit every block only once. The flag {@linkplain Block#active} is used to detect cycles (backward
      * edges).
      */
-    private int computeBlockOrder(Block block) {
+    private long computeBlockOrder(Block block) {
         if (block.visited) {
             if (block.active) {
                 // Reached block via backward branch.
@@ -557,7 +557,7 @@
             processLoopBlock(block);
         }
         if (block.isLoopHeader) {
-            assert Integer.bitCount(block.loops) == 1;
+            assert Long.bitCount(block.loops) == 1;
             loops &= ~block.loops;
         }
 
@@ -694,6 +694,6 @@
         }
         out.println();
 
-        out.print("loop_depth ").println(Integer.bitCount(block.loops));
+        out.print("loop_depth ").println(Long.bitCount(block.loops));
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Fri Jul 08 15:00:16 2011 +0200
@@ -31,6 +31,7 @@
 import com.oracle.max.graal.compiler.phases.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.extensions.*;
 import com.oracle.max.graal.graph.*;
 
 /**
@@ -52,7 +53,12 @@
     /**
      * The linear-scan ordered list of blocks.
      */
-    private List<LIRBlock> orderedBlocks;
+    private List<LIRBlock> linearScanOrder;
+
+    /**
+     * The order in which the code is emitted.
+     */
+    private List<LIRBlock> codeEmittingOrder;
 
     /**
      * Creates a new IR instance for the specified compilation.
@@ -76,18 +82,15 @@
 //            replacements.put(duplicate.start(), compilation.graph.start());
 //            compilation.graph.addDuplicate(duplicate.getNodes(), replacements);
 //        } else {
-            new GraphBuilderPhase(compilation, compilation.method, false, false).apply(compilation.graph);
+            new GraphBuilderPhase(compilation, compilation.method, false).apply(compilation.graph);
 //        }
 
-        //printGraph("After GraphBuilding", compilation.graph);
 
         if (GraalOptions.TestGraphDuplication) {
             new DuplicationPhase().apply(compilation.graph);
-            //printGraph("After Duplication", compilation.graph);
         }
 
         new DeadCodeEliminationPhase().apply(compilation.graph);
-        //printGraph("After DeadCodeElimination", compilation.graph);
 
         if (GraalOptions.Inline) {
             new InliningPhase(compilation, this, null).apply(compilation.graph);
@@ -100,6 +103,10 @@
             new DeadCodeEliminationPhase().apply(graph);
         }
 
+        if (GraalOptions.Extend) {
+            extensionOptimizations(graph);
+        }
+
         if (GraalOptions.OptLoops) {
             new LoopPhase().apply(graph);
             if (GraalOptions.OptCanonicalizer) {
@@ -108,9 +115,8 @@
             }
         }
 
-        if (GraalOptions.EscapeAnalysis /*&& compilation.method.toString().contains("simplify")*/) {
+        if (GraalOptions.EscapeAnalysis) {
             new EscapeAnalysisPhase(compilation, this).apply(graph);
-         //   new DeadCodeEliminationPhase().apply(graph);
             new CanonicalizerPhase().apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
         }
@@ -119,17 +125,20 @@
             new GlobalValueNumberingPhase().apply(graph);
         }
 
+        new LoweringPhase(compilation.runtime).apply(graph);
         if (GraalOptions.Lower) {
-            new LoweringPhase(compilation.runtime).apply(graph);
             new MemoryPhase().apply(graph);
             if (GraalOptions.OptGVN) {
                 new GlobalValueNumberingPhase().apply(graph);
             }
-            new ReadEliminationPhase().apply(graph);
+            if (GraalOptions.OptReadElimination) {
+                new ReadEliminationPhase().apply(graph);
+            }
         }
 
         IdentifyBlocksPhase schedule = new IdentifyBlocksPhase(true);
         schedule.apply(graph);
+        compilation.stats.loopCount = schedule.loopCount();
 
 
         List<Block> blocks = schedule.getBlocks();
@@ -140,6 +149,16 @@
             map.put(b, block);
             block.setInstructions(b.getInstructions());
             block.setLinearScanNumber(b.blockID());
+            block.setLoopDepth(b.loopDepth());
+            block.setLoopIndex(b.loopIndex());
+
+            if (b.isLoopEnd()) {
+                block.setLinearScanLoopEnd();
+            }
+
+            if (b.isLoopHeader()) {
+                block.setLinearScanLoopHeader();
+            }
 
             block.setFirstInstruction(b.firstNode());
             block.setLastInstruction(b.lastNode());
@@ -156,9 +175,8 @@
             }
         }
 
-        orderedBlocks = lirBlocks;
         valueToBlock = new HashMap<Node, LIRBlock>();
-        for (LIRBlock b : orderedBlocks) {
+        for (LIRBlock b : lirBlocks) {
             for (Node i : b.getInstructions()) {
                 valueToBlock.put(i, b);
             }
@@ -172,12 +190,12 @@
             GraalTimers.COMPUTE_LINEAR_SCAN_ORDER.start();
         }
 
-        ComputeLinearScanOrder clso = new ComputeLinearScanOrder(lirBlocks.size(), startBlock);
-        orderedBlocks = clso.linearScanOrder();
-        this.compilation.stats.loopCount = clso.numLoops();
+        ComputeLinearScanOrder clso = new ComputeLinearScanOrder(lirBlocks.size(), compilation.stats.loopCount, startBlock);
+        linearScanOrder = clso.linearScanOrder();
+        codeEmittingOrder = clso.codeEmittingOrder();
 
         int z = 0;
-        for (LIRBlock b : orderedBlocks) {
+        for (LIRBlock b : linearScanOrder) {
             b.setLinearScanNumber(z++);
         }
 
@@ -189,12 +207,33 @@
 
     }
 
+
+
+    public static ThreadLocal<ServiceLoader<Optimizer>> optimizerLoader = new ThreadLocal<ServiceLoader<Optimizer>>();
+
+    private void extensionOptimizations(Graph graph) {
+
+        ServiceLoader<Optimizer> serviceLoader = optimizerLoader.get();
+        if (serviceLoader == null) {
+            serviceLoader = ServiceLoader.load(Optimizer.class);
+            optimizerLoader.set(serviceLoader);
+        }
+
+        for (Optimizer o : serviceLoader) {
+            o.optimize(compilation.runtime, graph);
+        }
+    }
+
     /**
      * Gets the linear scan ordering of blocks as a list.
      * @return the blocks in linear scan order
      */
     public List<LIRBlock> linearScanOrder() {
-        return orderedBlocks;
+        return linearScanOrder;
+    }
+
+    public List<LIRBlock> codeEmittingOrder() {
+        return codeEmittingOrder;
     }
 
     public void printGraph(String phase, Graph graph) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryCheckpointNode.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryCheckpointNode.java	Fri Jul 08 15:00:16 2011 +0200
@@ -49,6 +49,6 @@
     }
 
     public List<Node> mergedNodes() {
-        return inputs().variablePart();
+        return variableInputs();
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java	Fri Jul 08 15:00:16 2011 +0200
@@ -28,7 +28,7 @@
 import com.sun.cri.ci.*;
 
 
-public abstract class AbstractVectorNode extends FixedNodeWithNext {
+public abstract class AbstractVectorNode extends StateSplit {
 
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_VECTOR = 0;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java	Fri Jul 08 15:00:16 2011 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
+import java.util.*;
+
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
@@ -72,6 +74,14 @@
         setObject(object);
     }
 
+    public void addDependency(Node x) {
+        variableInputs().add(x);
+    }
+
+    public List<Node> dependencies() {
+        return variableInputs();
+    }
+
     @Override
     public void print(LogStream out) {
         out.print("mem read from ").print(object());
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java	Fri Jul 08 15:00:16 2011 +0200
@@ -44,6 +44,10 @@
         super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
+    public void addGuard(GuardNode x) {
+        variableInputs().add(x);
+    }
+
     @Override
     public void accept(ValueVisitor v) {
         v.visitAnchor(this);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java	Fri Jul 08 15:00:16 2011 +0200
@@ -95,8 +95,7 @@
 
     @Override
     public Node copy(Graph into) {
-        ArrayLength x = new ArrayLength(null, into);
-        return x;
+        return new ArrayLength(null, into);
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java	Fri Jul 08 15:00:16 2011 +0200
@@ -31,9 +31,4 @@
     public BooleanNode(CiKind kind, int inputCount, int successorCount, Graph graph) {
         super(kind, inputCount, successorCount, graph);
     }
-
-
-    public BooleanNode negate() {
-        throw new IllegalStateException();
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CastNode.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class CastNode extends FloatingNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_NODE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+    public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+    }
+
+    public void setValue(Value n) {
+        inputs().set(super.inputCount() + INPUT_NODE, n);
+    }
+
+    public CastNode(CiKind kind, Value n, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setValue(n);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    CastNode conv = (CastNode) n;
+                    conv.setOperand(generator.load(conv.value()));
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("cast node ").print(value().toString());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new CastNode(kind, null, into);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java	Fri Jul 08 15:00:16 2011 +0200
@@ -23,6 +23,7 @@
 package com.oracle.max.graal.compiler.ir;
 
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
@@ -42,7 +43,7 @@
      * @param object the instruction producing the object
      * @param graph
      */
-    public CheckCast(Constant targetClassInstruction, Value object, Graph graph) {
+    public CheckCast(Value targetClassInstruction, Value object, Graph graph) {
         super(targetClassInstruction, object, CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
@@ -91,7 +92,29 @@
 
     @Override
     public Node copy(Graph into) {
-        CheckCast x = new CheckCast(null, null, into);
-        return x;
+        return new CheckCast(null, null, into);
     }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            CheckCast checkCast = (CheckCast) node;
+            Value object = checkCast.object();
+            RiType exactType = object.exactType();
+            if (exactType != null) {
+                return Constant.forBoolean(exactType.isSubtypeOf(checkCast.targetClass()), node.graph());
+            }
+            CiConstant constant = object.asConstant();
+            if (constant != null) {
+                assert constant.kind == CiKind.Object;
+                if (constant.isNull()) {
+                    return Constant.forBoolean(true, node.graph());
+                } else {
+                    // this should never happen - non-null constants are always expected to provide an exactType
+                    assert false;
+                }
+            }
+            return checkCast;
+        }
+    };
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java	Fri Jul 08 15:00:16 2011 +0200
@@ -95,6 +95,15 @@
         setY(y);
     }
 
+    @Override
+    public boolean valueEqual(Node i) {
+        if (i instanceof Compare) {
+            Compare compare = (Compare) i;
+            return compare.condition == condition && compare.unorderedIsTrue == unorderedIsTrue;
+        }
+        return super.valueEqual(i);
+    }
+
     /**
      * Gets the condition (comparison operation) for this instruction.
      * @return the condition
@@ -157,11 +166,6 @@
         return x;
     }
 
-    @Override
-    public BooleanNode negate() {
-        return new Compare(x(), condition.negate(), y(), graph());
-    }
-
     private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
         @Override
         public Node canonical(Node node) {
@@ -195,9 +199,9 @@
                     if (compare.condition == Condition.NE) {
                         isFalseCheck = !isFalseCheck;
                     }
-                    BooleanNode result = materializeNode.value();
+                    Value result = materializeNode.value();
                     if (isFalseCheck) {
-                        result = result.negate();
+                        result = new NegateBooleanNode(result, compare.graph());
                     }
                     if (GraalOptions.TraceCanonicalizer) {
                         TTY.println("Removed materialize replacing with " + result);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java	Fri Jul 08 15:00:16 2011 +0200
@@ -28,26 +28,22 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
-import com.sun.cri.ci.*;
 
 public final class ComputeLinearScanOrder {
 
     private final int maxBlockId; // the highest blockId of a block
     private int numBlocks; // total number of blocks (smaller than maxBlockId)
-    private int numLoops; // total number of loops
-    private boolean iterativeDominators; // method requires iterative computation of dominators
 
     List<LIRBlock> linearScanOrder; // the resulting list of blocks in correct order
+    List<LIRBlock> codeEmittingOrder;
 
     final BitMap visitedBlocks; // used for recursive processing of blocks
     final BitMap activeBlocks; // used for recursive processing of blocks
     final BitMap dominatorBlocks; // temporary BitMap used for computation of dominator
     final int[] forwardBranches; // number of incoming forward branches for each block
-    final List<LIRBlock> loopEndBlocks; // list of all loop end blocks collected during countEdges
-    BitMap2D loopMap; // two-dimensional bit set: a bit is set if a block is contained in a loop
     final List<LIRBlock> workList; // temporary list (used in markLoops and computeOrder)
+    final LIRBlock[] loopHeaders;
 
     // accessors for visitedBlocks and activeBlocks
     void initVisited() {
@@ -87,56 +83,24 @@
         return --forwardBranches[b.blockID()];
     }
 
-    // accessors for loopMap
-    boolean isBlockInLoop(int loopIdx, LIRBlock b) {
-        return loopMap.at(loopIdx, b.blockID());
-    }
-
-    void setBlockInLoop(int loopIdx, LIRBlock b) {
-        loopMap.setBit(loopIdx, b.blockID());
-    }
-
-    void clearBlockInLoop(int loopIdx, int blockId) {
-        loopMap.clearBit(loopIdx, blockId);
-    }
-
     // accessors for final result
     public List<LIRBlock> linearScanOrder() {
         return linearScanOrder;
     }
 
-    public int numLoops() {
-        return numLoops;
-    }
-
-    public ComputeLinearScanOrder(int maxBlockId, LIRBlock startBlock) {
+    public ComputeLinearScanOrder(int maxBlockId, int loopCount, LIRBlock startBlock) {
+        loopHeaders = new LIRBlock[loopCount];
 
         this.maxBlockId = maxBlockId;
         visitedBlocks = new BitMap(maxBlockId);
         activeBlocks = new BitMap(maxBlockId);
         dominatorBlocks = new BitMap(maxBlockId);
         forwardBranches = new int[maxBlockId];
-        loopEndBlocks = new ArrayList<LIRBlock>(8);
         workList = new ArrayList<LIRBlock>(8);
 
-        splitCriticalEdges();
-
         countEdges(startBlock, null);
-
-        if (numLoops > 0) {
-            markLoops();
-            clearNonNaturalLoops(startBlock);
-            assignLoopDepth(startBlock);
-        }
-
         computeOrder(startBlock);
-
         printBlocks();
-        assert verify();
-    }
-
-    void splitCriticalEdges() {
-        // TODO: move critical edge splitting from IR to here
     }
 
     /**
@@ -153,16 +117,6 @@
         }
 
         if (isActive(cur)) {
-            if (GraalOptions.TraceLinearScanLevel >= 3) {
-                TTY.println("backward branch");
-            }
-            assert isVisited(cur) : "block must be visited when block is active";
-            assert parent != null : "must have parent";
-
-            cur.setLinearScanLoopHeader();
-            parent.setLinearScanLoopEnd();
-
-            loopEndBlocks.add(parent);
             return;
         }
 
@@ -188,137 +142,11 @@
 
         clearActive(cur);
 
-        // Each loop has a unique number.
-        // When multiple loops are nested, assignLoopDepth assumes that the
-        // innermost loop has the lowest number. This is guaranteed by setting
-        // the loop number after the recursive calls for the successors above
-        // have returned.
-        if (cur.isLinearScanLoopHeader()) {
-            assert cur.loopIndex() == -1 : "cannot set loop-index twice";
-            if (GraalOptions.TraceLinearScanLevel >= 3) {
-                TTY.println("Block B%d is loop header of loop %d", cur.blockID(), numLoops);
-            }
-
-            cur.setLoopIndex(numLoops);
-            numLoops++;
-        }
-
         if (GraalOptions.TraceLinearScanLevel >= 3) {
             TTY.println("Finished counting edges for block B%d", cur.blockID());
         }
     }
 
-    void markLoops() {
-        if (GraalOptions.TraceLinearScanLevel >= 3) {
-            TTY.println("----- marking loops");
-        }
-
-        loopMap = new BitMap2D(numLoops, maxBlockId);
-
-        for (int i = loopEndBlocks.size() - 1; i >= 0; i--) {
-            LIRBlock loopEnd = loopEndBlocks.get(i);
-            LIRBlock loopStart = loopEnd.suxAt(0);
-            int loopIdx = loopStart.loopIndex();
-
-            if (GraalOptions.TraceLinearScanLevel >= 3) {
-                TTY.println("Processing loop from B%d to B%d (loop %d):", loopStart.blockID(), loopEnd.blockID(), loopIdx);
-            }
-            assert loopEnd.isLinearScanLoopEnd() : "loop end flag must be set";
-//            assert loopEnd.numberOfSux() == 1 : "incorrect number of successors";
-            assert loopStart.isLinearScanLoopHeader() : "loop header flag must be set";
-            assert loopIdx >= 0 && loopIdx < numLoops : "loop index not set";
-            assert workList.isEmpty() : "work list must be empty before processing";
-
-            // add the end-block of the loop to the working list
-            workList.add(loopEnd);
-            setBlockInLoop(loopIdx, loopEnd);
-            do {
-                LIRBlock cur = workList.remove(workList.size() - 1);
-
-                if (GraalOptions.TraceLinearScanLevel >= 3) {
-                    TTY.println("    processing B%d", cur.blockID());
-                }
-                assert isBlockInLoop(loopIdx, cur) : "bit in loop map must be set when block is in work list";
-
-                // recursive processing of all predecessors ends when start block of loop is reached
-                if (cur != loopStart) {
-                    for (int j = cur.numberOfPreds() - 1; j >= 0; j--) {
-                        LIRBlock pred = cur.predAt(j);
-
-                        if (!isBlockInLoop(loopIdx, pred)) {
-                            // this predecessor has not been processed yet, so add it to work list
-                            if (GraalOptions.TraceLinearScanLevel >= 3) {
-                                TTY.println("    pushing B%d", pred.blockID());
-                            }
-                            workList.add(pred);
-                            setBlockInLoop(loopIdx, pred);
-                        }
-                    }
-                }
-            } while (!workList.isEmpty());
-        }
-    }
-
-    // check for non-natural loops (loops where the loop header does not dominate
-    // all other loop blocks = loops with multiple entries).
-    // such loops are ignored
-    void clearNonNaturalLoops(LIRBlock startBlock) {
-        for (int i = numLoops - 1; i >= 0; i--) {
-            if (isBlockInLoop(i, startBlock)) {
-                // loop i contains the entry block of the method.
-                // this is not a natural loop, so ignore it
-                if (GraalOptions.TraceLinearScanLevel >= 2) {
-                    TTY.println("Loop %d is non-natural, so it is ignored", i);
-                }
-
-                for (int blockId = maxBlockId - 1; blockId >= 0; blockId--) {
-                    clearBlockInLoop(i, blockId);
-                }
-                iterativeDominators = true;
-            }
-        }
-    }
-
-    void assignLoopDepth(LIRBlock startBlock) {
-        if (GraalOptions.TraceLinearScanLevel >= 3) {
-            TTY.println("----- computing loop-depth and weight");
-        }
-        initVisited();
-
-        assert workList.isEmpty() : "work list must be empty before processing";
-        workList.add(startBlock);
-
-        do {
-            LIRBlock cur = workList.remove(workList.size() - 1);
-
-            if (!isVisited(cur)) {
-                setVisited(cur);
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
-                    TTY.println("Computing loop depth for block B%d", cur.blockID());
-                }
-
-                // compute loop-depth and loop-index for the block
-                assert cur.loopDepth() == 0 : "cannot set loop-depth twice";
-                int i;
-                int loopDepth = 0;
-                int minLoopIdx = -1;
-                for (i = numLoops - 1; i >= 0; i--) {
-                    if (isBlockInLoop(i, cur)) {
-                        loopDepth++;
-                        minLoopIdx = i;
-                    }
-                }
-                cur.setLoopDepth(loopDepth);
-                cur.setLoopIndex(minLoopIdx);
-
-                // append all unvisited successors to work list
-                for (i = cur.numberOfSux() - 1; i >= 0; i--) {
-                    workList.add(cur.suxAt(i));
-                }
-            }
-        } while (!workList.isEmpty());
-    }
-
     int computeWeight(LIRBlock cur) {
 
         // limit loop-depth to 15 bit (only for security reason, it will never be so big)
@@ -329,10 +157,10 @@
         // this is necessary for the (very rare) case that two successive blocks have
         // the same loop depth, but a different loop index (can happen for endless loops
         // with exception handlers)
-        if (!cur.isLinearScanLoopHeader()) {
-            weight |= 1 << curBit;
-        }
-        curBit--;
+//        if (!cur.isLinearScanLoopHeader()) {
+//            weight |= 1 << curBit;
+//        }
+//        curBit--;
 
         // loop end blocks (blocks that end with a backward branch) are added
         // after all other blocks of the loop.
@@ -360,10 +188,10 @@
 //        curBit--;
 
         // exceptions handlers are added as late as possible
-//        if (!cur.isExceptionEntry()) {
-//            weight |= 1 << curBit;
-//        }
-//        curBit--;
+        if (!cur.isExceptionEntry()) {
+            weight |= 1 << curBit;
+        }
+        curBit--;
 
         // guarantee that weight is > 0
         weight |= 1;
@@ -374,7 +202,7 @@
         return weight;
     }
 
-    boolean readyForProcessing(LIRBlock cur) {
+    private boolean readyForProcessing(LIRBlock cur) {
         // Discount the edge just traveled.
         // When the number drops to zero, all forward branches were processed
         if (decForwardBranches(cur) != 0) {
@@ -386,7 +214,7 @@
         return true;
     }
 
-    void sortIntoWorkList(LIRBlock cur) {
+    private void sortIntoWorkList(LIRBlock cur) {
         assert !workList.contains(cur) : "block already in work list";
 
         int curWeight = computeWeight(cur);
@@ -421,7 +249,7 @@
         }
     }
 
-    void appendBlock(LIRBlock cur) {
+    private void appendBlock(LIRBlock cur) {
         if (GraalOptions.TraceLinearScanLevel >= 3) {
             TTY.println("appending block B%d (weight 0x%06x) to linear-scan order", cur.blockID(), cur.linearScanNumber());
         }
@@ -432,31 +260,44 @@
         // be equal.
         cur.setLinearScanNumber(linearScanOrder.size());
         linearScanOrder.add(cur);
+
+        if (!cur.isLinearScanLoopHeader() || !GraalOptions.OptReorderLoops) {
+            codeEmittingOrder.add(cur);
+
+            if (cur.isLinearScanLoopEnd() && GraalOptions.OptReorderLoops) {
+                LIRBlock loopHeader = loopHeaders[cur.loopIndex()];
+                assert loopHeader != null;
+                codeEmittingOrder.add(loopHeader);
+
+                for (LIRBlock succ : loopHeader.blockSuccessors()) {
+                    if (succ.loopDepth() == loopHeader.loopDepth()) {
+                        succ.setAlign(true);
+                    }
+                }
+            }
+        } else {
+            loopHeaders[cur.loopIndex()] = cur;
+        }
     }
 
-    void computeOrder(LIRBlock startBlock) {
+    private void computeOrder(LIRBlock startBlock) {
         if (GraalOptions.TraceLinearScanLevel >= 3) {
             TTY.println("----- computing final block order");
         }
 
         // the start block is always the first block in the linear scan order
         linearScanOrder = new ArrayList<LIRBlock>(numBlocks);
-//        appendBlock(startBlock);
 
-        LIRBlock stdEntry = startBlock; //.suxAt(0);
+        codeEmittingOrder = new ArrayList<LIRBlock>(numBlocks);
 
         // start processing with standard entry block
         assert workList.isEmpty() : "list must be empty before processing";
 
-        if (readyForProcessing(stdEntry)) {
-            sortIntoWorkList(stdEntry);
-        } else {
-            throw new CiBailout("the stdEntry must be ready for processing (otherwise, the method has no start block)");
-        }
+        assert readyForProcessing(startBlock);
+        sortIntoWorkList(startBlock);
 
         do {
             LIRBlock cur = workList.remove(workList.size() - 1);
-
             appendBlock(cur);
 
             int i;
@@ -476,9 +317,6 @@
             TTY.println("----- loop information:");
             for (LIRBlock cur : linearScanOrder) {
                 TTY.print(String.format("%4d: B%02d: ", cur.linearScanNumber(), cur.blockID()));
-                for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) {
-                    TTY.print(String.format("%d = %b ", loopIdx, isBlockInLoop(loopIdx, cur)));
-                }
                 TTY.println(String.format(" . loopIndex: %2d, loopDepth: %2d", cur.loopIndex(), cur.loopDepth()));
             }
         }
@@ -513,75 +351,7 @@
         }
     }
 
-    boolean verify() {
-       /* assert linearScanOrder.size() == numBlocks : "wrong number of blocks in list";
-
-        if (GraalOptions.StressLinearScan) {
-            // blocks are scrambled when StressLinearScan is used
-            return true;
-        }
-
-        // check that all successors of a block have a higher linear-scan-number
-        // and that all predecessors of a block have a lower linear-scan-number
-        // (only backward branches of loops are ignored)
-        int i;
-        for (i = 0; i < linearScanOrder.size(); i++) {
-            BlockBegin cur = linearScanOrder.get(i);
-
-            assert cur.linearScanNumber() == i : "incorrect linearScanNumber";
-            assert cur.linearScanNumber() >= 0 && cur.linearScanNumber() == linearScanOrder.indexOf(cur) : "incorrect linearScanNumber";
-
-            for (BlockBegin sux : cur.end().successors()) {
-                assert sux.linearScanNumber() >= 0 && sux.linearScanNumber() == linearScanOrder.indexOf(sux) : "incorrect linearScanNumber";
-                if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd)) {
-                    assert cur.linearScanNumber() < sux.linearScanNumber() : "invalid order";
-                }
-                if (cur.loopDepth() == sux.loopDepth()) {
-                    assert cur.loopIndex() == sux.loopIndex() || sux.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index";
-                }
-            }
-
-            for (BlockBegin pred : cur.predecessors()) {
-                assert pred.linearScanNumber() >= 0 && pred.linearScanNumber() == linearScanOrder.indexOf(pred) : "incorrect linearScanNumber";
-                if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) {
-                    assert cur.linearScanNumber() > pred.linearScanNumber() : "invalid order";
-                }
-                if (cur.loopDepth() == pred.loopDepth()) {
-                    assert cur.loopIndex() == pred.loopIndex() || cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index";
-                }
-
-                assert cur.dominator().linearScanNumber() <= pred.linearScanNumber() : "dominator must be before predecessors";
-            }
-
-            // check dominator
-            if (i == 0) {
-                assert cur.dominator() == null : "first block has no dominator";
-            } else {
-                assert cur.dominator() != null : "all but first block must have dominator";
-            }
-            assert cur.numberOfPreds() != 1 || cur.dominator() == cur.predAt(0) || cur.isExceptionEntry() : "Single predecessor must also be dominator";
-        }
-
-        // check that all loops are continuous
-        for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) {
-            int blockIdx = 0;
-            assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "the first block must not be present in any loop";
-
-            // skip blocks before the loop
-            while (blockIdx < numBlocks && !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) {
-                blockIdx++;
-            }
-            // skip blocks of loop
-            while (blockIdx < numBlocks && isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) {
-                blockIdx++;
-            }
-            // after the first non-loop block : there must not be another loop-block
-            while (blockIdx < numBlocks) {
-                assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "loop not continuous in linear-scan order";
-                blockIdx++;
-            }
-        }
-*/
-        return true;
+    public List<LIRBlock> codeEmittingOrder() {
+        return codeEmittingOrder;
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Fri Jul 08 15:00:16 2011 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
-import com.sun.cri.bytecode.Bytecodes.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 
@@ -80,6 +79,16 @@
      */
     BT("|<|"),
 
+    /**
+     * Operation produced an overflow.
+     */
+    OF("overflow"),
+
+    /**
+     * Operation did not produce an overflow.
+     */
+    NOF("noOverflow"),
+
     TRUE("TRUE");
 
     public final String operator;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java	Fri Jul 08 15:00:16 2011 +0200
@@ -55,14 +55,6 @@
         v.visitConstant(this);
     }
 
-    @Override
-    public BooleanNode negate() {
-        if (kind != CiKind.Boolean) {
-            throw new IllegalStateException();
-        }
-        return Constant.forBoolean(!value.asBoolean(), graph());
-    }
-
     /**
      * Creates an instruction for a double constant.
      * @param d the double value for which to create the instruction
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java	Fri Jul 08 15:00:16 2011 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
 import com.oracle.max.graal.compiler.phases.LoweringPhase.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
@@ -98,7 +99,7 @@
         EndNode end = new EndNode(graph());
         LoopBegin loopBegin = new LoopBegin(graph());
         loopBegin.addEnd(end);
-        Phi loopVariable = new Phi(CiKind.Int, loopBegin, graph());
+        Phi loopVariable = new Phi(CiKind.Int, loopBegin, PhiType.Value, graph());
 
         if (reversed) {
             IntegerSub add = new IntegerSub(CiKind.Int, loopVariable, Constant.forInt(1, graph()), graph());
@@ -112,6 +113,7 @@
 
         LoopEnd loopEnd = new LoopEnd(graph());
         loopEnd.setLoopBegin(loopBegin);
+        loopBegin.setStateAfter(stateAfter());
         Compare condition;
         if (reversed) {
             condition = new Compare(loopVariable, Condition.GE, Constant.forInt(0, graph()), graph());
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Fri Jul 08 15:00:16 2011 +0200
@@ -66,7 +66,7 @@
         assertTrue(inputs().size() == 0, "inputs empty");
         assertTrue(successors().size() == 0, "successors empty");
         assertTrue(usages().size() <= 1, "at most one usage");
-        assertTrue(predecessors().size() <= 1, "at most one predecessor");
+        assertTrue(predecessors().size() <= 1, "at most one predecessor " + predecessors());
         return true;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java	Fri Jul 08 14:49:01 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.ir;
-
-import com.oracle.max.graal.compiler.debug.*;
-import com.oracle.max.graal.graph.*;
-import com.sun.cri.ci.*;
-import com.sun.cri.ri.*;
-
-/**
- * This instruction takes an exception object and has two successors:
- * The catchSuccessor is called whenever the exception matches the given type, otherwise otherSuccessor is called.
- */
-public final class ExceptionDispatch extends ControlSplit {
-
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_EXCEPTION = 0;
-
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
-
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction producing the exception object.
-     */
-     public Value exception() {
-        return (Value) inputs().get(super.inputCount() + INPUT_EXCEPTION);
-    }
-
-    public Value setException(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n);
-    }
-
-    private final RiType catchType;
-
-    /**
-     * Constructs a new ExceptionDispatch instruction.
-     */
-    public ExceptionDispatch(Value exception, FixedNode catchSuccessor, FixedNode otherSuccessor, RiType catchType, Graph graph) {
-        super(CiKind.Int, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        setException(exception);
-        setBlockSuccessor(0, otherSuccessor);
-        setBlockSuccessor(1, catchSuccessor);
-        this.catchType = catchType;
-    }
-
-    public RiType catchType() {
-        return catchType;
-    }
-
-    /**
-     * Gets the block corresponding to the catch block.
-     * @return the true successor
-     */
-    public FixedNode catchSuccessor() {
-        return blockSuccessor(1);
-    }
-
-    /**
-     * Gets the block corresponding to the rest of the dispatch chain.
-     * @return the false successor
-     */
-    public FixedNode otherSuccessor() {
-        return blockSuccessor(0);
-    }
-
-    /**
-     * Gets the block corresponding to the specified outcome of the branch.
-     * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
-     * @return the corresponding successor
-     */
-    public FixedNode successor(boolean istrue) {
-        return blockSuccessor(istrue ? 1 : 0);
-    }
-
-    @Override
-    public void accept(ValueVisitor v) {
-        v.visitExceptionDispatch(this);
-    }
-
-    @Override
-    public void print(LogStream out) {
-        out.print("exception_dispatch ").
-        print(exception()).
-        print(' ').
-        print("instanceof").
-        print(' ').
-        print(catchType().name()).
-        print(" then ").
-        print(catchSuccessor().toString()).
-        print(" else B").
-        print(otherSuccessor().toString());
-    }
-
-    @Override
-    public String shortName() {
-        return "Dispatch " + catchType().name();
-    }
-
-    @Override
-    public Node copy(Graph into) {
-        ExceptionDispatch x = new ExceptionDispatch(null, null, null, catchType, into);
-        return x;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Fri Jul 08 15:00:16 2011 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
+import java.util.*;
+
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction;
@@ -54,7 +56,7 @@
     }
 
     public void addNode(BooleanNode node) {
-        inputs().add(node);
+        variableInputs().add(node);
     }
 
     @Override
@@ -75,14 +77,16 @@
         @Override
         public Node canonical(Node node) {
             FixedGuard fixedGuard = (FixedGuard) node;
-            for (Node n : fixedGuard.inputs()) {
+            Iterator<Node> iter = fixedGuard.variableInputs().iterator();
+            while (iter.hasNext()) {
+                Node n = iter.next();
                 if (n instanceof Constant) {
                     Constant c = (Constant) n;
                     if (c.asConstant().asBoolean()) {
                         if (GraalOptions.TraceCanonicalizer) {
                             TTY.println("Removing redundant fixed guard " + fixedGuard);
                         }
-                        fixedGuard.inputs().remove(c);
+                        iter.remove();
                     } else {
                         if (GraalOptions.TraceCanonicalizer) {
                             TTY.println("Replacing fixed guard " + fixedGuard + " with deoptimization node");
@@ -92,7 +96,7 @@
                 }
             }
 
-            if (fixedGuard.inputs().size() == 0) {
+            if (fixedGuard.variableInputs().size() == 0) {
                 return fixedGuard.next();
             }
             return fixedGuard;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java	Fri Jul 08 15:00:16 2011 +0200
@@ -55,8 +55,9 @@
         inputs().set(super.inputCount() + INPUT_NODE, n);
     }
 
-    public GuardNode(Graph graph) {
+    public GuardNode(BooleanNode node, Graph graph) {
         super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setNode(node);
     }
 
     @Override
@@ -71,7 +72,12 @@
 
     @Override
     public Node copy(Graph into) {
-        return new GuardNode(into);
+        return new GuardNode(null, into);
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof GuardNode;
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java	Fri Jul 08 15:00:16 2011 +0200
@@ -23,10 +23,12 @@
 package com.oracle.max.graal.compiler.ir;
 
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
 
 /**
  * The {@code InstanceOf} instruction represents an instanceof test.
@@ -36,13 +38,15 @@
     private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
 
+    private boolean nullIsTrue;
+
     /**
      * Constructs a new InstanceOf instruction.
      * @param targetClass the target class of the instanceof check
      * @param object the instruction producing the object input to this instruction
      * @param graph
      */
-    public InstanceOf(Constant targetClassInstruction, Value object, Graph graph) {
+    public InstanceOf(Constant targetClassInstruction, Value object, boolean nullIsTrue, Graph graph) {
         super(targetClassInstruction, object, CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
@@ -66,12 +70,39 @@
     }
 
     @Override
-    public BooleanNode negate() {
-        return new NotInstanceOf(targetClassInstruction(), object(), graph());
+    public Node copy(Graph into) {
+        return new InstanceOf(null, null, nullIsTrue, into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
     }
 
-    @Override
-    public Node copy(Graph into) {
-        return new InstanceOf(null, null, into);
-    }
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            InstanceOf isInstance = (InstanceOf) node;
+            Value object = isInstance.object();
+            RiType exactType = object.exactType();
+            if (exactType != null) {
+                return Constant.forBoolean(exactType.isSubtypeOf(isInstance.targetClass()), node.graph());
+            }
+            CiConstant constant = object.asConstant();
+            if (constant != null) {
+                assert constant.kind == CiKind.Object;
+                if (constant.isNull()) {
+                    return Constant.forBoolean(false, node.graph());
+                } else {
+                    // this should never happen - non-null constants are always expected to provide an exactType
+                    assert false;
+                }
+            }
+            return isInstance;
+        }
+    };
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Fri Jul 08 15:00:16 2011 +0200
@@ -41,11 +41,21 @@
     private static final int SUCCESSOR_COUNT = 1;
     private static final int SUCCESSOR_EXCEPTION_EDGE = 0;
 
+    private boolean canInline = true;
+
     @Override
     protected int inputCount() {
         return super.inputCount() + argumentCount;
     }
 
+    public boolean canInline() {
+        return canInline;
+    }
+
+    public void setCanInline(boolean b) {
+        canInline = b;
+    }
+
     @Override
     protected int successorCount() {
         return super.successorCount() + SUCCESSOR_COUNT;
@@ -204,6 +214,7 @@
     @Override
     public Node copy(Graph into) {
         Invoke x = new Invoke(bci, opcode, kind, new Value[argumentCount], target, returnType, into);
+        x.setCanInline(canInline);
         return x;
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java	Fri Jul 08 15:00:16 2011 +0200
@@ -23,6 +23,7 @@
 package com.oracle.max.graal.compiler.ir;
 
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.bytecode.*;
@@ -67,7 +68,7 @@
      */
     public IsNonNull(Value object, Graph graph) {
         super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        assert object == null || object.kind == CiKind.Object;
+        assert object == null || object.kind == CiKind.Object : object;
         setObject(object);
     }
 
@@ -107,4 +108,30 @@
     public Node copy(Graph into) {
         return new IsNonNull(null, into);
     }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            IsNonNull isNonNull = (IsNonNull) node;
+            Value object = isNonNull.object();
+            if (object instanceof NewInstance || object instanceof NewArray) {
+                return Constant.forBoolean(true, node.graph());
+            }
+            CiConstant constant = object.asConstant();
+            if (constant != null) {
+                assert constant.kind == CiKind.Object;
+                return Constant.forBoolean(constant.isNonNull(), node.graph());
+            }
+            return isNonNull;
+        }
+    };
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java	Fri Jul 08 15:00:16 2011 +0200
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.bytecode.*;
@@ -127,4 +128,27 @@
     public Node copy(Graph into) {
         return new IsType(null, type, into);
     }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            IsType isType = (IsType) node;
+            Value object = isType.object();
+            RiType exactType = object.exactType();
+            if (exactType != null) {
+                return Constant.forBoolean(exactType == isType.type, node.graph());
+            }
+            // constants return the correct exactType, so they are handled by the code above
+            return isType;
+        }
+    };
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java	Fri Jul 08 15:00:16 2011 +0200
@@ -23,6 +23,8 @@
 package com.oracle.max.graal.compiler.ir;
 
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.LoweringOp;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -85,6 +87,16 @@
         return false;
     }
 
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LoweringOp.class) {
+            return (T) LoweringPhase.DELEGATE_TO_RUNTIME;
+        }
+        return super.lookup(clazz);
+    }
+
     @Override
     public Node copy(Graph into) {
         LoadIndexed x = new LoadIndexed(null, null, null, elementKind(), into);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java	Fri Jul 08 15:00:16 2011 +0200
@@ -52,11 +52,11 @@
     /**
      * The instruction which produces the input value to this instruction.
      */
-     public BooleanNode value() {
-        return (BooleanNode) inputs().get(super.inputCount() + INPUT_VALUE);
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
     }
 
-    public void setValue(BooleanNode n) {
+    public void setValue(Value n) {
         inputs().set(super.inputCount() + INPUT_VALUE, n);
     }
 
@@ -67,7 +67,7 @@
      * @param kind the result type of this instruction
      * @param graph
      */
-    public MaterializeNode(BooleanNode value, Graph graph) {
+    public MaterializeNode(Value value, Graph graph) {
         super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         setValue(value);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Fri Jul 08 15:00:16 2011 +0200
@@ -76,20 +76,20 @@
     }
 
     public int endIndex(EndNode end) {
-        assert inputs().variablePart().contains(end);
-        return inputs().variablePart().indexOf(end);
+        assert variableInputs().contains(end);
+        return variableInputs().indexOf(end);
     }
 
     public void addEnd(EndNode end) {
-        inputs().variablePart().add(end);
+        variableInputs().add(end);
     }
 
     public int endCount() {
-        return inputs().variablePart().size();
+        return variableInputs().size();
     }
 
     public EndNode endAt(int index) {
-        return (EndNode) inputs().variablePart().get(index);
+        return (EndNode) variableInputs().get(index);
     }
 
     @Override
@@ -197,7 +197,7 @@
             while (!hasPhisOnStack && i < state.stackSize()) {
                 Value value = state.stackAt(i);
                 hasPhisOnStack = isPhiAtBlock(value);
-                if (value != null && !(value instanceof Phi && ((Phi) value).isDead())) {
+                if (value != null) {
                     i += value.kind.sizeInSlots();
                 } else {
                     i++;
@@ -208,7 +208,7 @@
                 Value value = state.localAt(i);
                 hasPhisInLocals = isPhiAtBlock(value);
                 // also ignore illegal HiWords
-                if (value != null && !(value instanceof Phi && ((Phi) value).isDead())) {
+                if (value != null) {
                     i += value.kind.sizeInSlots();
                 } else {
                     i++;
@@ -227,11 +227,7 @@
                 if (value != null) {
                     out.println(stateString(j, value));
                     // also ignore illegal HiWords
-                    if (value instanceof Phi && ((Phi) value).isDead()) {
-                        j +=  1;
-                    } else {
-                        j += value.kind.sizeInSlots();
-                    }
+                    j += value.kind.sizeInSlots();
                 } else {
                     j++;
                 }
@@ -314,16 +310,13 @@
     }
 
     public void removeEnd(EndNode pred) {
-        int predIndex = inputs().variablePart().indexOf(pred);
+        int predIndex = variableInputs().indexOf(pred);
         assert predIndex != -1;
-        inputs().variablePart().remove(predIndex);
+        variableInputs().remove(predIndex);
 
         for (Node usage : usages()) {
             if (usage instanceof Phi) {
-                Phi phi = (Phi) usage;
-                if (!phi.isDead()) {
-                    phi.removeInput(predIndex);
-                }
+                ((Phi) usage).removeInput(predIndex);
             }
         }
     }
@@ -346,6 +339,6 @@
     }
 
     public List<Node> phiPredecessors() {
-        return Collections.unmodifiableList(inputs().variablePart());
+        return Collections.unmodifiableList(variableInputs());
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code ArrayLength} instruction gets the length of an array.
+ */
+public final class NegateBooleanNode extends BooleanNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_NODE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the array object.
+     */
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+    }
+
+    public Value setValue(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_NODE, n);
+    }
+
+    /**
+     * Constructs a new ArrayLength instruction.
+     * @param array the instruction producing the array
+     * @param newFrameState the state after executing this instruction
+     */
+    public NegateBooleanNode(Value value, Graph graph) {
+        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setValue(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof NegateBooleanNode;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(value()).print("!");
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new NegateBooleanNode(null, into);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static final CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            NegateBooleanNode negateNode = (NegateBooleanNode) node;
+            Value value = negateNode.value();
+            if (value instanceof NegateBooleanNode) {
+                return ((NegateBooleanNode) value).value();
+            } else if (value instanceof Constant) {
+                return Constant.forBoolean(!value.asConstant().asBoolean(), node.graph());
+            }
+            return negateNode;
+        }
+    };
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java	Fri Jul 08 15:00:16 2011 +0200
@@ -27,7 +27,6 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeField;
 import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeOp;
-import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 
@@ -36,8 +35,6 @@
  */
 public abstract class NewArray extends FixedNodeWithNext {
 
-    private static final EscapeOp ESCAPE = new NewArrayEscapeOp();
-
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_LENGTH = 0;
 
@@ -109,7 +106,7 @@
         return super.lookup(clazz);
     }
 
-    private static class NewArrayEscapeOp implements EscapeOp {
+    private static final EscapeOp ESCAPE = new EscapeOp() {
 
         @Override
         public boolean canAnalyze(Node node) {
@@ -120,19 +117,7 @@
 
         @Override
         public boolean escape(Node node, Node usage) {
-            if (usage instanceof IsNonNull) {
-                IsNonNull x = (IsNonNull) usage;
-                assert x.object() == node;
-                return false;
-            } else if (usage instanceof IsType) {
-                IsType x = (IsType) usage;
-                assert x.object() == node;
-                return false;
-            } else if (usage instanceof FrameState) {
-                FrameState x = (FrameState) usage;
-                assert x.inputs().contains(node);
-                return true;
-            } else if (usage instanceof LoadIndexed) {
+            if (usage instanceof LoadIndexed) {
                 LoadIndexed x = (LoadIndexed) usage;
                 assert x.array() == node;
                 CiConstant index = x.index().asConstant();
@@ -152,19 +137,15 @@
                 if (index == null || length == null || index.asInt() < 0 || index.asInt() >= length.asInt()) {
                     return true;
                 }
-                return x.value() == node;
-            } else if (usage instanceof AccessMonitor) {
-                AccessMonitor x = (AccessMonitor) usage;
-                assert x.object() == node;
-                return false;
+                return x.value() == node && x.array() != node;
             } else if (usage instanceof ArrayLength) {
                 ArrayLength x = (ArrayLength) usage;
                 assert x.array() == node;
                 return false;
-            } else if (usage instanceof VirtualObject) {
+            } else if (usage instanceof VirtualObjectField) {
                 return false;
             } else {
-                return true;
+                return super.escape(node, usage);
             }
         }
 
@@ -182,56 +163,33 @@
 
         @Override
         public void beforeUpdate(Node node, Node usage) {
-            if (usage instanceof IsNonNull) {
-                IsNonNull x = (IsNonNull) usage;
-                if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) {
-                    FixedGuard guard = (FixedGuard) x.usages().get(0);
-                    guard.replaceAndDelete(guard.next());
-                }
-                x.delete();
-            } else if (usage instanceof IsType) {
-                IsType x = (IsType) usage;
-                assert x.type() == ((NewArray) node).exactType();
-                if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) {
-                    FixedGuard guard = (FixedGuard) x.usages().get(0);
-                    guard.replaceAndDelete(guard.next());
-                }
-                x.delete();
-            } else if (usage instanceof AccessMonitor) {
-                AccessMonitor x = (AccessMonitor) usage;
-                x.replaceAndDelete(x.next());
-            } else if (usage instanceof ArrayLength) {
+            if (usage instanceof ArrayLength) {
                 ArrayLength x = (ArrayLength) usage;
                 x.replaceAndDelete(((NewArray) node).dimension(0));
+            } else {
+                super.beforeUpdate(node, usage);
             }
         }
 
         @Override
-        public EscapeField updateState(Node node, Node current, Map<Object, EscapeField> fields, Map<EscapeField, Value> fieldState) {
+        public int updateState(Node node, Node current, Map<Object, Integer> fieldIndex, Value[] fieldState) {
             if (current instanceof AccessIndexed) {
-                int index = ((AccessIndexed) current).index().asConstant().asInt();
-                EscapeField field = fields.get(index);
-                if (current instanceof LoadIndexed) {
-                    LoadIndexed x = (LoadIndexed) current;
-                    if (x.array() == node) {
-                        x.replaceAtUsages(fieldState.get(field));
+                AccessIndexed x = (AccessIndexed) current;
+                if (x.array() == node) {
+                    int index = ((AccessIndexed) current).index().asConstant().asInt();
+                    if (current instanceof LoadIndexed) {
+                        x.replaceAtUsages(fieldState[index]);
                         assert x.usages().size() == 0;
                         x.replaceAndDelete(x.next());
-                    }
-                } else if (current instanceof StoreIndexed) {
-                    StoreIndexed x = (StoreIndexed) current;
-                    if (x.array() == node) {
-                        fieldState.put(field, x.value());
+                    } else if (current instanceof StoreIndexed) {
+                        fieldState[index] = ((StoreIndexed) x).value();
                         assert x.usages().size() == 0;
-                        WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(x.graph());
-                        checkpoint.setStateAfter(x.stateAfter());
-                        checkpoint.setNext(x.next());
-                        x.replaceAndDelete(checkpoint);
-                        return field;
+                        x.replaceAndDelete(x.next());
+                        return index;
                     }
                 }
             }
-            return null;
+            return -1;
         }
-    }
+    };
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Fri Jul 08 15:00:16 2011 +0200
@@ -27,7 +27,6 @@
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeField;
 import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeOp;
-import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -36,7 +35,6 @@
  * The {@code NewInstance} instruction represents the allocation of an instance class object.
  */
 public final class NewInstance extends FixedNodeWithNext {
-    private static final EscapeOp ESCAPE = new NewInstanceEscapeOp();
 
     private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
@@ -109,7 +107,7 @@
         return super.lookup(clazz);
     }
 
-    private static class NewInstanceEscapeOp implements EscapeOp {
+    private static final EscapeOp ESCAPE = new EscapeOp() {
 
         @Override
         public boolean canAnalyze(Node node) {
@@ -118,41 +116,25 @@
 
         @Override
         public boolean escape(Node node, Node usage) {
-            if (usage instanceof IsNonNull) {
-                IsNonNull x = (IsNonNull) usage;
-                assert x.object() == node;
-                return false;
-            } else if (usage instanceof IsType) {
-                IsType x = (IsType) usage;
-                assert x.object() == node;
-                return false;
-            } else if (usage instanceof FrameState) {
-                FrameState x = (FrameState) usage;
-                assert x.inputs().contains(node);
-                return true;
-            } else if (usage instanceof LoadField) {
+            if (usage instanceof LoadField) {
                 LoadField x = (LoadField) usage;
                 assert x.object() == node;
                 return x.field().isResolved() == false;
             } else if (usage instanceof StoreField) {
                 StoreField x = (StoreField) usage;
-                return x.value() == node;
+                return x.value() == node && x.object() != node;
             } else if (usage instanceof StoreIndexed) {
                 StoreIndexed x = (StoreIndexed) usage;
                 assert x.value() == node;
                 return true;
-            } else if (usage instanceof AccessMonitor) {
-                AccessMonitor x = (AccessMonitor) usage;
-                assert x.object() == node;
-                return false;
-            } else if (usage instanceof VirtualObject) {
+            } else if (usage instanceof VirtualObjectField) {
                 return false;
             } else if (usage instanceof RegisterFinalizer) {
                 RegisterFinalizer x = (RegisterFinalizer) usage;
                 assert x.object() == node;
                 return false;
             } else {
-                return true;
+                return super.escape(node, usage);
             }
         }
 
@@ -170,56 +152,34 @@
 
         @Override
         public void beforeUpdate(Node node, Node usage) {
-            if (usage instanceof IsNonNull) {
-                IsNonNull x = (IsNonNull) usage;
-                if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) {
-                    FixedGuard guard = (FixedGuard) x.usages().get(0);
-                    guard.replaceAndDelete(guard.next());
-                }
-                x.delete();
-            } else if (usage instanceof IsType) {
-                IsType x = (IsType) usage;
-                assert x.type() == ((NewInstance) node).instanceClass();
-                if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) {
-                    FixedGuard guard = (FixedGuard) x.usages().get(0);
-                    guard.replaceAndDelete(guard.next());
-                }
-                x.delete();
-            } else if (usage instanceof AccessMonitor) {
-                AccessMonitor x = (AccessMonitor) usage;
-                x.replaceAndDelete(x.next());
-            } else if (usage instanceof RegisterFinalizer) {
+            if (usage instanceof RegisterFinalizer) {
                 RegisterFinalizer x = (RegisterFinalizer) usage;
                 x.replaceAndDelete(x.next());
+            } else {
+                super.beforeUpdate(node, usage);
             }
         }
 
         @Override
-        public EscapeField updateState(Node node, Node current, Map<Object, EscapeField> fields, Map<EscapeField, Value> fieldState) {
+        public int updateState(Node node, Node current, Map<Object, Integer> fieldIndex, Value[] fieldState) {
             if (current instanceof AccessField) {
-                EscapeField field = fields.get(((AccessField) current).field());
-                if (current instanceof LoadField) {
-                    LoadField x = (LoadField) current;
-                    if (x.object() == node) {
-                        assert fieldState.get(field) != null : field + ", " + ((AccessField) current).field() + ((AccessField) current).field().hashCode();
-                        x.replaceAtUsages(fieldState.get(field));
+                AccessField x = (AccessField) current;
+                if (x.object() == node) {
+                    int field = fieldIndex.get(((AccessField) current).field());
+                    if (current instanceof LoadField) {
+                        assert fieldState[field] != null : field + ", " + ((AccessField) current).field();
+                        x.replaceAtUsages(fieldState[field]);
                         assert x.usages().size() == 0;
                         x.replaceAndDelete(x.next());
-                    }
-                } else if (current instanceof StoreField) {
-                    StoreField x = (StoreField) current;
-                    if (x.object() == node) {
-                        fieldState.put(field, x.value());
+                    } else if (current instanceof StoreField) {
+                        fieldState[field] = ((StoreField) x).value();
                         assert x.usages().size() == 0;
-                        WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(x.graph());
-                        checkpoint.setStateAfter(x.stateAfter());
-                        checkpoint.setNext(x.next());
-                        x.replaceAndDelete(checkpoint);
+                        x.replaceAndDelete(x.next());
                         return field;
                     }
                 }
             }
-            return null;
+            return -1;
         }
-    }
+    };
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NotInstanceOf.java	Fri Jul 08 14:49:01 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.ir;
-
-import com.oracle.max.graal.compiler.debug.*;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.graph.*;
-import com.sun.cri.bytecode.*;
-import com.sun.cri.ci.*;
-
-/**
- * The {@code InstanceOf} instruction represents an instanceof test.
- */
-public final class NotInstanceOf extends TypeCheck {
-
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
-    /**
-     * Constructs a new InstanceOf instruction.
-     * @param targetClass the target class of the instanceof check
-     * @param object the instruction producing the object input to this instruction
-     * @param graph
-     */
-    public NotInstanceOf(Constant targetClassInstruction, Value object, Graph graph) {
-        super(targetClassInstruction, object, CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-    }
-
-    @Override
-    public void accept(ValueVisitor v) {
-    }
-
-    @Override
-    public int valueNumber() {
-        return Util.hash1(Bytecodes.INSTANCEOF, object());
-    }
-
-    @Override
-    public boolean valueEqual(Node i) {
-        return i instanceof NotInstanceOf;
-    }
-
-    @Override
-    public void print(LogStream out) {
-        out.print("instanceof(").print(object()).print(") ").print(CiUtil.toJavaName(targetClass()));
-    }
-
-    @Override
-    public BooleanNode negate() {
-        return new InstanceOf(targetClassInstruction(), object(), graph());
-    }
-
-    @Override
-    public Node copy(Graph into) {
-        return new NotInstanceOf(null, null, into);
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Fri Jul 08 15:00:16 2011 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.ir.StateSplit.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 
@@ -42,7 +43,7 @@
 
     private static final int SUCCESSOR_COUNT = 0;
 
-    private boolean isDead;
+    private final PhiType type;
 
     @Override
     protected int inputCount() {
@@ -66,21 +67,31 @@
         inputs().set(super.inputCount() + INPUT_MERGE, n);
     }
 
-    public Phi(CiKind kind, Merge merge, Graph graph) {
+    public static enum PhiType {
+        Value,          // normal value phis
+        Memory,         // memory phis
+        Virtual         // phis used for VirtualObjectField merges
+    }
+
+    public Phi(CiKind kind, Merge merge, PhiType type, Graph graph) {
         super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.type = type;
         setMerge(merge);
     }
 
-    Phi(CiKind kind, Graph graph) {
+    private Phi(CiKind kind, PhiType type, Graph graph) {
         super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.type = type;
+    }
+
+    public PhiType type() {
+        return type;
     }
 
     @Override
     public boolean verify() {
         assertTrue(merge() != null);
-        if (!isDead()) {
-            assertTrue(merge().phiPredecessorCount() == valueCount());
-        }
+        assertTrue(merge().phiPredecessorCount() == valueCount(), merge().phiPredecessorCount() + "==" + valueCount());
         return true;
     }
 
@@ -91,7 +102,7 @@
      * @return the instruction that produced the value in the i'th predecessor
      */
     public Value valueAt(int i) {
-        return (Value) inputs().variablePart().get(i);
+        return (Value) variableInputs().get(i);
     }
 
     public void setValueAt(int i, Value x) {
@@ -103,7 +114,7 @@
      * @return the number of inputs in this phi
      */
     public int valueCount() {
-        return inputs().variablePart().size();
+        return variableInputs().size();
     }
 
     @Override
@@ -111,17 +122,6 @@
         v.visitPhi(this);
     }
 
-    /**
-     * Make this phi illegal if types were not merged correctly.
-     */
-    public void makeDead() {
-        isDead = true;
-    }
-
-    public boolean isDead() {
-        return isDead;
-    }
-
     @Override
     public void print(LogStream out) {
         out.print("phi function (");
@@ -143,25 +143,24 @@
             }
             str.append(valueAt(i) == null ? "-" : valueAt(i).id());
         }
-        if (isDead()) {
-            return "Phi: dead (" + str + ")";
+        if (type == PhiType.Value) {
+            return "Phi: (" + str + ")";
         } else {
-            return "Phi: (" + str + ")";
+            return type + "Phi: (" + str + ")";
         }
     }
 
     public void addInput(Node y) {
-        inputs().variablePart().add(y);
+        variableInputs().add(y);
     }
 
     public void removeInput(int index) {
-        inputs().variablePart().remove(index);
+        variableInputs().remove(index);
     }
 
     @Override
     public Node copy(Graph into) {
-        Phi x = new Phi(kind, into);
-        x.isDead = isDead;
+        Phi x = new Phi(kind, type, into);
         return x;
     }
 
@@ -176,4 +175,62 @@
             }
         };
     }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+
+        @Override
+        public Node canonical(Node node) {
+            Phi phiNode = (Phi) node;
+//            if (phiNode.valueCount() != 2 || phiNode.merge().endCount() != 2 || phiNode.merge().phis().size() != 1) {
+//                return phiNode;
+//            }
+//            if (!(phiNode.valueAt(0) instanceof Constant && phiNode.valueAt(1) instanceof Constant)) {
+//                return phiNode;
+//            }
+//            Merge merge = phiNode.merge();
+//            Node end0 = merge.endAt(0);
+//            Node end1 = merge.endAt(1);
+//            if (end0.predecessors().size() != 1 || end1.predecessors().size() != 1) {
+//                return phiNode;
+//            }
+//            Node endPred0 = end0.predecessors().get(0);
+//            Node endPred1 = end1.predecessors().get(0);
+//            if (endPred0 != endPred1 || !(endPred0 instanceof If)) {
+//                return phiNode;
+//            }
+//            If ifNode = (If) endPred0;
+//            if (ifNode.predecessors().size() != 1) {
+//                return phiNode;
+//            }
+//            boolean inverted = ((If) endPred0).trueSuccessor() == end1;
+//            CiConstant trueValue = phiNode.valueAt(inverted ? 1 : 0).asConstant();
+//            CiConstant falseValue = phiNode.valueAt(inverted ? 0 : 1).asConstant();
+//            if (trueValue.kind != CiKind.Int || falseValue.kind != CiKind.Int) {
+//                return phiNode;
+//            }
+//            if ((trueValue.asInt() == 0 || trueValue.asInt() == 1) && (falseValue.asInt() == 0 || falseValue.asInt() == 1) && (trueValue.asInt() != falseValue.asInt())) {
+//                MaterializeNode result;
+//                if (trueValue.asInt() == 1) {
+//                    result = new MaterializeNode(ifNode.compare(), phiNode.graph());
+//                } else {
+//                    result = new MaterializeNode(new NegateBooleanNode(ifNode.compare(), phiNode.graph()), phiNode.graph());
+//                }
+//                Node next = merge.next();
+//                merge.setNext(null);
+//                ifNode.predecessors().get(0).successors().replace(ifNode, next);
+//                return result;
+//            }
+            return phiNode;
+        }
+    };
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Fri Jul 08 15:00:16 2011 +0200
@@ -107,11 +107,11 @@
             }
 
             if (needsCheck) {
-                if (GraalOptions.TraceGVN) {
+                if (GraalOptions.TraceCanonicalizer) {
                     TTY.println("Could not canonicalize finalizer " + object + " (declaredType=" + declaredType + ", exactType=" + exactType + ")");
                 }
             } else {
-                if (GraalOptions.TraceGVN) {
+                if (GraalOptions.TraceCanonicalizer) {
                     TTY.println("Canonicalized finalizer for object " + object);
                 }
                 return finalizer.next();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java	Fri Jul 08 15:00:16 2011 +0200
@@ -56,8 +56,8 @@
         return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_AFTER);
     }
 
-    public FrameState setStateAfter(FrameState n) {
-        return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_AFTER, n);
+    public void setStateAfter(FrameState n) {
+        inputs().set(super.inputCount() + INPUT_STATE_AFTER, n);
     }
 
     /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java	Fri Jul 08 15:00:16 2011 +0200
@@ -23,6 +23,8 @@
 package com.oracle.max.graal.compiler.ir;
 
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 
@@ -82,6 +84,15 @@
         out.print(array()).print('[').print(index()).print("] := ").print(value()).print(" (").print(kind.typeChar).print(')');
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LoweringOp.class) {
+            return (T) LoweringPhase.DELEGATE_TO_RUNTIME;
+        }
+        return super.lookup(clazz);
+    }
+
     @Override
     public Node copy(Graph into) {
         StoreIndexed x = new StoreIndexed(null, null, null, elementKind(), null, into);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java	Fri Jul 08 15:00:16 2011 +0200
@@ -61,11 +61,11 @@
     /**
      * The instruction that loads the target class object that is used by this checkcast.
      */
-     public Constant targetClassInstruction() {
-        return (Constant) inputs().get(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION);
+     public Value targetClassInstruction() {
+        return (Value) inputs().get(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION);
     }
 
-    private void setTargetClassInstruction(Constant n) {
+    private void setTargetClassInstruction(Value n) {
         inputs().set(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION, n);
     }
 
@@ -75,7 +75,7 @@
      * @return the target class
      */
     public RiType targetClass() {
-        return (RiType) targetClassInstruction().asConstant().asObject();
+        return targetClassInstruction() instanceof Constant ? (RiType) targetClassInstruction().asConstant().asObject() : null;
     }
 
     /**
@@ -87,7 +87,7 @@
      * @param successorCount
      * @param graph
      */
-    public TypeCheck(Constant targetClassInstruction, Value object, CiKind kind, int inputCount, int successorCount, Graph graph) {
+    public TypeCheck(Value targetClassInstruction, Value object, CiKind kind, int inputCount, int successorCount, Graph graph) {
         super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
         setObject(object);
         setTargetClassInstruction(targetClassInstruction);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java	Fri Jul 08 15:00:16 2011 +0200
@@ -69,7 +69,6 @@
     public abstract void visitStoreIndexed(StoreIndexed i);
     public abstract void visitTableSwitch(TableSwitch i);
     public abstract void visitDeoptimize(Deoptimize deoptimize);
-    public abstract void visitExceptionDispatch(ExceptionDispatch exceptionDispatch);
     public abstract void visitUnwind(Unwind unwind);
     public abstract void visitLoopBegin(LoopBegin loopBegin);
     public abstract void visitLoopEnd(LoopEnd loopEnd);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObject.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObject.java	Fri Jul 08 15:00:16 2011 +0200
@@ -33,9 +33,7 @@
 
 public class VirtualObject extends FloatingNode {
 
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_OBJECT = 0;
-    private static final int INPUT_INPUT = 1;
+    private static final int INPUT_COUNT = 0;
 
     private static final int SUCCESSOR_COUNT = 0;
 
@@ -49,48 +47,13 @@
         return super.successorCount() + SUCCESSOR_COUNT;
     }
 
-    /**
-     * The instruction that specifies the old state of the virtual object.
-     */
-     public VirtualObject object() {
-        return (VirtualObject) inputs().get(super.inputCount() + INPUT_OBJECT);
-    }
-
-    private VirtualObject setObject(VirtualObject n) {
-        return (VirtualObject) inputs().set(super.inputCount() + INPUT_OBJECT, n);
-    }
-
-    /**
-     * The instruction that contains the new state of the specified field.
-     */
-     public Value input() {
-        return (Value) inputs().get(super.inputCount() + INPUT_INPUT);
-    }
-
-    public Value setInput(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_INPUT, n);
-    }
-
-    private EscapeField field;
     private EscapeField[] fields;
     private RiType type;
 
-    /**
-     * Constructs a new ArrayLength instruction.
-     * @param array the instruction producing the array
-     * @param newFrameState the state after executing this instruction
-     */
-    public VirtualObject(VirtualObject object, Value input, EscapeField field, RiType type, EscapeField[] fields, Graph graph) {
+    public VirtualObject(RiType type, EscapeField[] fields, Graph graph) {
         super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        this.field = field;
         this.type = type;
         this.fields = fields;
-        setObject(object);
-        setInput(input);
-    }
-
-    public EscapeField field() {
-        return field;
     }
 
     public RiType type() {
@@ -110,23 +73,22 @@
     public Map<Object, Object> getDebugProperties() {
         Map<Object, Object> properties = super.getDebugProperties();
         properties.put("type", type);
-        properties.put("field", field);
         return properties;
     }
 
     @Override
     public String shortName() {
-        return "VirtualObject " + field.name();
+        return "VirtualObject " + type.name();
     }
 
     @Override
     public void print(LogStream out) {
-        out.print(object()).print(".").print(field.name()).print("=").print(input());
+        out.print("virtualobject ").print(type.name());
     }
 
     @Override
     public Node copy(Graph into) {
-        VirtualObject x = new VirtualObject(null, null, field, type, fields, into);
+        VirtualObject x = new VirtualObject(type, fields, into);
         return x;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObjectField.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public class VirtualObjectField extends FloatingNode {
+
+    private static final int INPUT_COUNT = 3;
+    private static final int INPUT_OBJECT = 0;
+    private static final int INPUT_LAST_STATE = 1;
+    private static final int INPUT_INPUT = 2;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that specifies the virtual object instance.
+     */
+     public VirtualObject object() {
+        return (VirtualObject) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    private VirtualObject setObject(VirtualObject n) {
+        return (VirtualObject) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    /**
+     * The instruction that specifies the old state of the virtual object.
+     */
+     public FloatingNode lastState() {
+        return (FloatingNode) inputs().get(super.inputCount() + INPUT_LAST_STATE);
+    }
+
+    private FloatingNode setLastState(FloatingNode n) {
+        return (FloatingNode) inputs().set(super.inputCount() + INPUT_LAST_STATE, n);
+    }
+
+    /**
+     * The instruction that contains the new state of the specified field.
+     */
+     public Value input() {
+        return (Value) inputs().get(super.inputCount() + INPUT_INPUT);
+    }
+
+    public Value setInput(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_INPUT, n);
+    }
+
+    private int index;
+
+    /**
+     * Constructs a new ArrayLength instruction.
+     * @param array the instruction producing the array
+     * @param newFrameState the state after executing this instruction
+     */
+    public VirtualObjectField(VirtualObject object, FloatingNode lastState, Value input, int index, Graph graph) {
+        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.index = index;
+        setObject(object);
+        setLastState(lastState);
+        setInput(input);
+    }
+
+    public int index() {
+        return index;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        // nothing to do...
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("index", index);
+        return properties;
+    }
+
+    @Override
+    public String shortName() {
+        return "VirtualObjectField " + object().fields()[index].name();
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(object()).print(".").print(object().fields()[index].name()).print("=").print(input());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        VirtualObjectField x = new VirtualObjectField(null, null, null, index, into);
+        return x;
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java	Fri Jul 08 15:00:16 2011 +0200
@@ -30,12 +30,12 @@
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.ir.*;
-import com.oracle.max.graal.compiler.lir.FrameMap.*;
+import com.oracle.max.graal.compiler.lir.FrameMap.StackBlock;
 import com.oracle.max.graal.compiler.util.*;
 import com.sun.cri.ci.*;
-import com.sun.cri.ci.CiTargetMethod.*;
+import com.sun.cri.ci.CiTargetMethod.Mark;
 import com.sun.cri.ri.*;
-import com.sun.cri.xir.CiXirAssembler.*;
+import com.sun.cri.xir.CiXirAssembler.XirMark;
 
 /**
  * The {@code LIRAssembler} class definition.
@@ -108,6 +108,10 @@
 
     void emitBlock(LIRBlock block) {
 
+        if (block.align()) {
+            emitAlignment();
+        }
+
         block.setBlockEntryPco(codePos());
 
         if (GraalOptions.PrintLIRWithAssembly) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java	Fri Jul 08 15:00:16 2011 +0200
@@ -27,6 +27,7 @@
 import com.oracle.max.asm.*;
 import com.oracle.max.graal.compiler.alloc.*;
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
@@ -44,6 +45,7 @@
     private List<LIRBlock> predecessors = new ArrayList<LIRBlock>(4);
     private List<LIRBlock> successors = new ArrayList<LIRBlock>(4);
     private LIRDebugInfo debugInfo;
+    private boolean align;
 
     /**
      * Bit map specifying which {@linkplain OperandPool operands} are live upon entry to this block.
@@ -106,6 +108,14 @@
         return firstLirInstructionID;
     }
 
+    public boolean align() {
+        return align;
+    }
+
+    public void setAlign(boolean b) {
+        align = b;
+    }
+
     public void setFirstLirInstructionId(int firstLirInstructionId) {
         this.firstLirInstructionID = firstLirInstructionId;
     }
@@ -174,8 +184,7 @@
     }
 
     public int loopDepth() {
-        // TODO(tw): Set correct loop depth.
-        return 0;
+        return loopDepth;
     }
 
     public int loopIndex() {
@@ -284,4 +293,8 @@
         LIROpcode code = lirInstruction.code;
         return code == LIROpcode.Branch || code == LIROpcode.TableSwitch;
     }
+
+    public boolean isExceptionEntry() {
+        return firstInstruction() instanceof ExceptionObject;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Fri Jul 08 15:00:16 2011 +0200
@@ -42,7 +42,7 @@
                 Node canonical = op.canonical(node);
                 if (canonical != node) {
                     node.replaceAndDelete(canonical);
-                    nodeWorkList.replaced(canonical, node, EdgeType.USAGES);
+                    nodeWorkList.replaced(canonical, node, true, EdgeType.USAGES);
                     //System.out.println("-->" + n + " canonicalized to " + canonical);
                     GraalMetrics.NodesCanonicalized++;
                 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Fri Jul 08 15:00:16 2011 +0200
@@ -28,7 +28,6 @@
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.ir.*;
-import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.graph.*;
 
 
@@ -77,8 +76,8 @@
             if (current instanceof AbstractVectorNode) {
                 for (Node usage : current.usages()) {
                     flood.add(usage);
-                }
-            }
+        }
+    }
         }
     }
 
@@ -105,29 +104,6 @@
                         endNode.replaceAndDelete(loop.next());
                         loop.delete();
                     }
-                } else if (node instanceof Merge) {
-                    for (Node n : node.usages()) {
-                        if (n instanceof Phi) {
-                            Phi phi = (Phi) n;
-                            if (phi.usages().size() == 1 && phi.usages().get(0) instanceof VirtualObject) {
-                                // (tw) This VirtualObject instance is implicitely dead, because the CFG to it (i.e. the store that produced it) is dead! => fix this in escape analysis
-                                VirtualObject virtualObject = (VirtualObject) phi.usages().get(0);
-                                virtualObject.replaceAndDelete(virtualObject.object());
-                            }
-                        }
-                    }
-                }
-
-
-                if (IdentifyBlocksPhase.isFixed(node)) {
-                    for (Node n : new ArrayList<Node>(node.usages())) {
-                        if (n instanceof VirtualObject) {
-                            // (tw) This VirtualObject instance is implicitely dead, because the CFG to it (i.e. the
-                            // store that produced it) is dead! => fix this in Escape analysis
-                            VirtualObject virtualObject = (VirtualObject) n;
-                            virtualObject.replaceAndDelete(virtualObject.object());
-                        }
-                    }
                 }
             }
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Fri Jul 08 15:00:16 2011 +0200
@@ -23,43 +23,294 @@
 package com.oracle.max.graal.compiler.phases;
 
 import java.util.*;
-import java.util.Map.Entry;
 
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
 import com.oracle.max.graal.compiler.observer.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
-import com.sun.cri.ri.*;
 
 
 public class EscapeAnalysisPhase extends Phase {
 
+    public interface MergeableState <T> {
+        T clone();
+        void merge(Merge merge, Collection<T> withStates);
+        void loopBegin(LoopBegin loopBegin);
+        void loopEnd(LoopEnd loopEnd, T loopEndState);
+    }
 
-    public static class BlockExitState {
-        public final Map<EscapeField, Value> fieldState;
-        public VirtualObject obj;
+    public abstract static class PostOrderNodeIterator<T extends MergeableState<T>> {
+
+        private final NodeBitMap visitedEnds;
+        private final Deque<FixedNode> nodeQueue;
+        private final HashMap<FixedNode, T> nodeStates;
+        private final FixedNode start;
+
+        protected T state;
+
+        public PostOrderNodeIterator(FixedNode start, T initialState) {
+            visitedEnds = start.graph().createNodeBitMap();
+            nodeQueue = new ArrayDeque<FixedNode>();
+            nodeStates = new HashMap<FixedNode, T>();
+            this.start = start;
+            this.state = initialState;
+        }
+
+        public void apply() {
+            FixedNode current = start;
+
+            do {
+                if (current instanceof Invoke) {
+                    invoke((Invoke) current);
+                    queueSuccessors(current);
+                    current = nextQueuedNode();
+                } else if (current instanceof LoopBegin) {
+                    state.loopBegin((LoopBegin) current);
+                    nodeStates.put(current, state.clone());
+                    loopBegin((LoopBegin) current);
+                    current = ((LoopBegin) current).next();
+                    assert current != null;
+                } else if (current instanceof LoopEnd) {
+                    T loopBeginState = nodeStates.get(((LoopEnd) current).loopBegin());
+                    if (loopBeginState != null) {
+                        loopBeginState.loopEnd((LoopEnd) current, state);
+                    }
+                    loopEnd((LoopEnd) current);
+                    current = nextQueuedNode();
+                } else if (current instanceof Merge) {
+                    merge((Merge) current);
+                    current = ((Merge) current).next();
+                    assert current != null;
+                } else if (current instanceof FixedNodeWithNext) {
+                    FixedNode next = ((FixedNodeWithNext) current).next();
+                    node(current);
+                    current = next;
+                    assert current != null;
+                } else if (current instanceof EndNode) {
+                    end((EndNode) current);
+                    queueMerge((EndNode) current);
+                    current = nextQueuedNode();
+                } else if (current instanceof Deoptimize) {
+                    deoptimize((Deoptimize) current);
+                    current = nextQueuedNode();
+                } else if (current instanceof Return) {
+                    returnNode((Return) current);
+                    current = nextQueuedNode();
+                } else if (current instanceof Unwind) {
+                    unwind((Unwind) current);
+                    current = nextQueuedNode();
+                } else if (current instanceof ControlSplit) {
+                    controlSplit((ControlSplit) current);
+                    queueSuccessors(current);
+                    current = nextQueuedNode();
+                } else {
+                    assert false : current.shortName();
+                }
+            } while(current != null);
+        }
+
+        private void queueSuccessors(FixedNode x) {
+            nodeStates.put(x, state);
+            for (Node node : x.successors()) {
+                if (node != null) {
+                    nodeQueue.addFirst((FixedNode) node);
+                }
+            }
+        }
 
-        public BlockExitState() {
-            this.fieldState = new HashMap<EscapeField, Value>();
+        private FixedNode nextQueuedNode() {
+            int maxIterations = nodeQueue.size();
+            while (maxIterations-- > 0) {
+                FixedNode node = nodeQueue.removeFirst();
+                if (node instanceof Merge) {
+                    Merge merge = (Merge) node;
+                    state = nodeStates.get(merge.endAt(0)).clone();
+                    ArrayList<T> states = new ArrayList<T>(merge.endCount() - 1);
+                    for (int i = 1; i < merge.endCount(); i++) {
+                        T other = nodeStates.get(merge.endAt(i));
+                        assert other != null;
+                        states.add(other);
+                    }
+                    state.merge(merge, states);
+                    return merge;
+                } else {
+                    assert node.predecessors().size() == 1;
+                    state = nodeStates.get(node.predecessors().get(0)).clone();
+                    return node;
+                }
+            }
+            return null;
+        }
+
+        private void queueMerge(EndNode end) {
+            assert !visitedEnds.isMarked(end);
+            assert !nodeStates.containsKey(end);
+            nodeStates.put(end, state);
+            visitedEnds.mark(end);
+            Merge merge = end.merge();
+            boolean endsVisited = true;
+            for (int i = 0; i < merge.endCount(); i++) {
+                if (!visitedEnds.isMarked(merge.endAt(i))) {
+                    endsVisited = false;
+                    break;
+                }
+            }
+            if (endsVisited) {
+                nodeQueue.add(merge);
+            }
+        }
+
+        protected abstract void node(FixedNode node);
+
+        protected void end(EndNode endNode) {
+            node(endNode);
+        }
+
+        protected void merge(Merge merge) {
+            node(merge);
+        }
+
+        protected void loopBegin(LoopBegin loopBegin) {
+            node(loopBegin);
+        }
+
+        protected void loopEnd(LoopEnd loopEnd) {
+            node(loopEnd);
+        }
+
+        protected void deoptimize(Deoptimize deoptimize) {
+            node(deoptimize);
+        }
+
+        protected void controlSplit(ControlSplit controlSplit) {
+            node(controlSplit);
+        }
+
+        protected void returnNode(Return returnNode) {
+            node(returnNode);
+        }
+
+        protected void invoke(Invoke invoke) {
+            node(invoke);
+        }
+
+        protected void unwind(Unwind unwind) {
+            node(unwind);
         }
     }
 
+    public static class BlockExitState implements MergeableState<BlockExitState> {
+        public final Value[] fieldState;
+        public final VirtualObject virtualObject;
+        public FloatingNode virtualObjectField;
+
+        public BlockExitState(EscapeField[] fields, VirtualObject virtualObject) {
+            this.fieldState = new Value[fields.length];
+            this.virtualObject = virtualObject;
+            this.virtualObjectField = null;
+            for (int i = 0; i < fields.length; i++) {
+                fieldState[i] = Constant.defaultForKind(fields[i].kind(), virtualObject.graph());
+                virtualObjectField = new VirtualObjectField(virtualObject, virtualObjectField, fieldState[i], i, virtualObject.graph());
+            }
+        }
+
+        public BlockExitState(BlockExitState state) {
+            this.fieldState = state.fieldState.clone();
+            this.virtualObject = state.virtualObject;
+            this.virtualObjectField = state.virtualObjectField;
+        }
+
+        public void updateField(int fieldIndex) {
+            virtualObjectField = new VirtualObjectField(virtualObject, virtualObjectField, fieldState[fieldIndex], fieldIndex, virtualObject.graph());
+        }
+
+        @Override
+        public BlockExitState clone() {
+            return new BlockExitState(this);
+        }
+
+        @Override
+        public void merge(Merge merge, Collection<BlockExitState> withStates) {
+            Phi vobjPhi = null;
+            Phi[] valuePhis = new Phi[fieldState.length];
+            for (BlockExitState other : withStates) {
+                if (virtualObjectField != other.virtualObjectField && vobjPhi == null) {
+                    vobjPhi = new Phi(CiKind.Illegal, merge, PhiType.Virtual, virtualObject.graph());
+                    vobjPhi.addInput(virtualObjectField);
+                    virtualObjectField = vobjPhi;
+                }
+                for (int i2 = 0; i2 < fieldState.length; i2++) {
+                    if (fieldState[i2] != other.fieldState[i2] && valuePhis[i2] == null) {
+                        valuePhis[i2] = new Phi(fieldState[i2].kind, merge, PhiType.Value, virtualObject.graph());
+                        valuePhis[i2].addInput(fieldState[i2]);
+                        fieldState[i2] = valuePhis[i2];
+                    }
+                }
+            }
+            for (BlockExitState other : withStates) {
+                if (vobjPhi != null) {
+                    vobjPhi.addInput(other.virtualObjectField);
+                }
+                for (int i2 = 0; i2 < fieldState.length; i2++) {
+                    if (valuePhis[i2] != null) {
+                        valuePhis[i2].addInput(other.fieldState[i2]);
+                    }
+                }
+            }
+            assert vobjPhi == null || vobjPhi.valueCount() == withStates.size() + 1;
+            for (int i2 = 0; i2 < fieldState.length; i2++) {
+                if (valuePhis[i2] != null) {
+                    virtualObjectField = new VirtualObjectField(virtualObject, virtualObjectField, valuePhis[i2], i2, virtualObject.graph());
+                    assert valuePhis[i2].valueCount() == withStates.size() + 1;
+                }
+            }
+        }
+
+        @Override
+        public void loopBegin(LoopBegin loopBegin) {
+            Phi vobjPhi = null;
+            vobjPhi = new Phi(CiKind.Illegal, loopBegin, PhiType.Virtual, virtualObject.graph());
+            vobjPhi.addInput(virtualObjectField);
+            virtualObjectField = vobjPhi;
+            for (int i2 = 0; i2 < fieldState.length; i2++) {
+                Phi valuePhi = new Phi(fieldState[i2].kind, loopBegin, PhiType.Value, virtualObject.graph());
+                valuePhi.addInput(fieldState[i2]);
+                fieldState[i2] = valuePhi;
+                updateField(i2);
+            }
+        }
+
+        @Override
+        public void loopEnd(LoopEnd x, BlockExitState loopEndState) {
+            while (!(virtualObjectField instanceof Phi)) {
+                virtualObjectField = ((VirtualObjectField) virtualObjectField).lastState();
+            }
+            ((Phi) virtualObjectField).addInput(loopEndState.virtualObjectField);
+            assert ((Phi) virtualObjectField).valueCount() == 2;
+            for (int i2 = 0; i2 < fieldState.length; i2++) {
+                ((Phi) fieldState[i2]).addInput(loopEndState.fieldState[i2]);
+                assert ((Phi) fieldState[i2]).valueCount() == 2;
+            }
+        }
+    }
+
+
     public class EscapementFixup {
 
         private List<Block> blocks;
-        private final Map<Object, EscapeField> fields = new HashMap<Object, EscapeField>();
+        private final Map<Object, Integer> fields = new HashMap<Object, Integer>();
         private final Map<Block, BlockExitState> exitStates = new HashMap<Block, BlockExitState>();
 
         private final EscapeOp op;
-        private Graph graph;
+        private final Graph graph;
         private final Node node;
-        private RiType type;
         private EscapeField[] escapeFields;
 
         public EscapementFixup(EscapeOp op, Graph graph, Node node) {
@@ -74,217 +325,36 @@
         }
 
         public void removeAllocation() {
-            final IdentifyBlocksPhase identifyBlocksPhase = new IdentifyBlocksPhase(true);
-            identifyBlocksPhase.apply(graph);
-            blocks = identifyBlocksPhase.getBlocks();
-
-            final HashMap<Phi, EscapeField> phis = new HashMap<Phi, EscapeField>();
-            final Block startBlock = identifyBlocksPhase.getNodeToBlock().get(node);
-            assert startBlock != null;
-            type = ((Value) node).exactType();
-            escapeFields = op.fields(node);
-            for (EscapeField field : escapeFields) {
-                fields.put(field.representation(), field);
-            }
-
-            Block.iteratePostOrder(blocks, new BlockClosure() {
-
-                public void apply(Block block) {
-                    if (GraalOptions.TraceEscapeAnalysis) {
-                        TTY.println("Block %d", block.blockID());
-                    }
-//                    for (Node n : block.getInstructions()) {
-//                        TTY.println("  %d %s", n.id(), n.shortName());
-//                    }
-//                    for (Block b : block.getSuccessors()) {
-//                        TTY.print(" %d", b.blockID());
-//                    }
-//                    TTY.println();
-
-                    BlockExitState state = new BlockExitState();
-                    if (/*block == startBlock ||*/ block.getPredecessors().size() == 0) {
-                        state.obj = null;
-                    } else {
-                        List<Block> predecessors = block.getPredecessors();
-                        Set<EscapeField> mergedFields = new HashSet<EscapeField>();
-
-                        BlockExitState predState = exitStates.get(predecessors.get(0));
-                        state.obj = predState == null ? null : predState.obj;
-
-                        for (int i = 0; i < predecessors.size(); i++) {
-                            BlockExitState exitState = exitStates.get(predecessors.get(i));
-                            if (exitState == null) {
-                                // (tw) What about an object that is allocated in a loop. We are merging in the values of the old allocation?; Now solved by "if" below.
-                                mergedFields.addAll(fields.values());
-                                state.obj = null;
-                                break;
-                            } else {
-                                for (EscapeField field : fields.values()) {
-                                    if (state.fieldState.get(field) == null) {
-                                        state.fieldState.put(field, exitState.fieldState.get(field));
-                                        if (i != 0) {
-                                            // We need to merge this field too!
-                                            mergedFields.add(field);
-                                        }
-                                    } else if (state.fieldState.get(field) != exitState.fieldState.get(field)) {
-                                        mergedFields.add(field);
-                                    }
-                                }
-                            }
-                        }
-                        if (block.firstNode() instanceof LoopBegin) {
-                            if (predState.obj == null) {
-                                state.obj = null;
-                                mergedFields.clear();
-                            }
-                        }
+            assert node instanceof FixedNodeWithNext;
 
-                        if (!mergedFields.isEmpty()) {
-                            assert block.firstNode() instanceof Merge : "unexpected: " + block.firstNode().shortName() + " " + block.firstNode().id();
-                            for (EscapeField field : mergedFields) {
-                                Phi phi = new Phi(field.kind().stackKind(), (Merge) block.firstNode(), graph);
-                                state.fieldState.put(field, phi);
-                                phis.put(phi, field);
-                                state.obj = new VirtualObject(state.obj, phi, field, type, escapeFields, graph);
-                            }
-                        }
-                    }
-
-                    Node current;
-                    if (block.firstNode() instanceof StartNode) {
-                        current = ((StartNode) block.firstNode()).next();
-                    } else {
-                        current = block.firstNode();
-                    }
-                    while (current != block.lastNode()) {
-                        Node next = ((FixedNodeWithNext) current).next();
-                        FrameState stateAfter = null;
-                        if (current instanceof StateSplit) {
-                            stateAfter = ((StateSplit) current).stateAfter();
-                        }
-                        if (current == node) {
-                            for (EscapeField field : fields.values()) {
-                                Constant value = Constant.defaultForKind(field.kind(), graph);
-                                state.fieldState.put(field, value);
-                                state.obj = new VirtualObject(state.obj, value, field, type, escapeFields, graph);
-                            }
-                        } else {
-                            EscapeField changedField = op.updateState(node, current, fields, state.fieldState);
-                            if (changedField != null) {
-                                state.obj = new VirtualObject(state.obj, state.fieldState.get(changedField), changedField, type, escapeFields, graph);
-                            }
-                        }
-                        if (stateAfter != null) {
-                            updateFrameState(stateAfter, state.obj);
-                        }
-                        current = next;
-                    }
+            escapeFields = op.fields(node);
+            for (int i = 0; i < escapeFields.length; i++) {
+                fields.put(escapeFields[i].representation(), i);
+            }
+            final VirtualObject virtual = new VirtualObject(((Value) node).exactType(), escapeFields, graph);
+            if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
+                TTY.println("new virtual object: " + virtual);
+            }
+            node.replaceAtUsages(virtual);
+            final FixedNode next = ((FixedNodeWithNext) node).next();
+            node.replaceAndDelete(next);
 
-                    if (GraalOptions.TraceEscapeAnalysis) {
-                        TTY.print(" block end state: ");
-                        for (Entry<EscapeField, Value> entry : state.fieldState.entrySet()) {
-                            TTY.print("%s->%s ", entry.getKey().name(), entry.getValue());
-                        }
-                        TTY.println();
+            final BlockExitState startState = new BlockExitState(escapeFields, virtual);
+            final PostOrderNodeIterator<?> iterator = new PostOrderNodeIterator<BlockExitState>(next, startState) {
+                @Override
+                protected void node(FixedNode node) {
+                    int changedField = op.updateState(virtual, node, fields, state.fieldState);
+                    if (changedField != -1) {
+                        state.updateField(changedField);
                     }
-                    exitStates.put(block, state);
-                }
-            });
-
-            for (Entry<Phi, EscapeField> entry : phis.entrySet()) {
-                Phi phi = entry.getKey();
-                EscapeField field = entry.getValue();
-                Block block = identifyBlocksPhase.getNodeToBlock().get(entry.getKey().merge());
-
-                List<Block> predecessors = block.getPredecessors();
-                assert predecessors.size() > 0;
-                Node simple = exitStates.get(predecessors.get(0)).fieldState.get(field);
-                for (int i = 1; i < predecessors.size(); i++) {
-                    BlockExitState exitState = exitStates.get(predecessors.get(i));
-                    if (exitState.fieldState.get(field) != simple) {
-                        simple = null;
-                        break;
-                    }
-                }
-                if (simple != null) {
-                    // (tw) Should never be reached, because Phi verification fails here..
-                    phi.replaceAndDelete(simple);
-                } else {
-                    for (int i = 0; i < predecessors.size(); i++) {
-                        BlockExitState exitState = exitStates.get(predecessors.get(i));
-                        assert exitState != null;
-                        Node value = exitState.fieldState.get(field);
-                        if (GraalOptions.TraceEscapeAnalysis) {
-                            TTY.println("fixing phi %d with %s", phi.id(), value);
-                        }
-                        if (value == null) {
-                            phi.addInput(Constant.defaultForKind(field.kind(), graph));
-                        } else {
-                            phi.addInput(value);
+                    if (!node.isDeleted() && node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) {
+                        if (state.virtualObjectField != null) {
+                            ((StateSplit) node).stateAfter().addVirtualObjectMapping(state.virtualObjectField);
                         }
                     }
                 }
-            }
-            // the rest of the usages should be dead frame states...
-            for (Node usage : new ArrayList<Node>(node.usages())) {
-                if (usage instanceof IsNonNull) {
-                    usage.replaceAndDelete(Constant.forBoolean(true, graph));
-                } else if (usage instanceof RegisterFinalizer) {
-                    usage.replaceAndDelete(((RegisterFinalizer) usage).next());
-                } else {
-                    assert usage instanceof FrameState || usage instanceof VirtualObject : "usage: " + usage;
-                    usage.inputs().replace(node, Node.Null);
-                }
-            }
-
-            if (node instanceof FixedNodeWithNext) {
-                node.replaceAndDelete(((FixedNodeWithNext) node).next());
-            } else {
-                node.delete();
-            }
-        }
-
-        private void updateFrameState(FrameState frameState, VirtualObject current) {
-            for (int i = 0; i < frameState.inputs().size(); i++) {
-                if (frameState.inputs().get(i) == node) {
-                    frameState.inputs().set(i, current);
-                } else if (frameState.inputs().get(i) instanceof VirtualObject) {
-                    VirtualObject obj = (VirtualObject) frameState.inputs().get(i);
-                    do {
-                        updateVirtualObject(obj, current);
-                        obj = obj.object();
-                    } while (obj != null);
-                }
-            }
-            FrameState outer = frameState.outerFrameState();
-            if (outer != null) {
-                boolean duplicate = false;
-                for (int i = 0; i < outer.inputs().size(); i++) {
-                    if (outer.inputs().get(i) == node) {
-                        duplicate = true;
-                    }
-                }
-                // (tw) need to fully duplicate also if there is a reference to "node" in an outer framestate?
-                duplicate = true;
-                if (duplicate) {
-                    outer = outer.duplicate(outer.bci);
-                    frameState.setOuterFrameState(outer);
-                }
-                updateFrameState(outer, current);
-            }
-        }
-
-        private void updateVirtualObject(VirtualObject obj, VirtualObject current) {
-            if (obj.input() == node) {
-                // (tw) don't we have similar issues here like in framestate dup? We are updating a shared data structure here..
-                obj.setInput(current);
-            } else if (obj.input() instanceof VirtualObject) {
-                VirtualObject obj2 = (VirtualObject) obj.input();
-                do {
-                    updateVirtualObject(obj2, current);
-                    obj2 = obj2.object();
-                } while (obj2 != null);
-            }
+            };
+            iterator.apply();
         }
 
         private void process() {
@@ -305,9 +375,6 @@
 
     @Override
     protected void run(Graph graph) {
-        if (compilation.method.name().contains("removeEnd") || compilation.method.name().contains("emitCode")) {
-            return;
-        }
         for (Node node : graph.getNodes()) {
             EscapeOp op = node.lookup(EscapeOp.class);
             if (op != null && op.canAnalyze(node)) {
@@ -344,10 +411,10 @@
                             TTY.println("%n!!!!!!!! non-escaping object: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method);
                         }
                         new EscapementFixup(op, graph, node).apply();
+                        if (compilation.compiler.isObserved()) {
+                            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After escape", graph, true, false));
+                        }
                         new PhiSimplifier(graph);
-                        if (compilation.compiler.isObserved()) {
-                            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After escape " + node.id(), graph, true, false));
-                        }
                         break;
                     }
                     if (weight < minimumWeight) {
@@ -364,6 +431,12 @@
                     }
                     new InliningPhase(compilation, ir, invokes).apply(graph);
                     new DeadCodeEliminationPhase().apply(graph);
+                    if (node.isDeleted()) {
+                        if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
+                            TTY.println("%n!!!!!!!! object died while performing escape analysis: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method);
+                        }
+                        break;
+                    }
                     exits.clear();
                     invokes.clear();
                 } while (iterations++ < 3);
@@ -423,17 +496,57 @@
         }
     }
 
-    public static interface EscapeOp extends Op {
+    public abstract static class EscapeOp implements Op {
+
+        public abstract boolean canAnalyze(Node node);
 
-        boolean canAnalyze(Node node);
-
-        boolean escape(Node node, Node usage);
+        public boolean escape(Node node, Node usage) {
+            if (usage instanceof IsNonNull) {
+                IsNonNull x = (IsNonNull) usage;
+                assert x.object() == node;
+                return false;
+            } else if (usage instanceof IsType) {
+                IsType x = (IsType) usage;
+                assert x.object() == node;
+                return false;
+            } else if (usage instanceof FrameState) {
+                FrameState x = (FrameState) usage;
+                assert x.inputs().contains(node);
+                return true;
+            } else if (usage instanceof AccessMonitor) {
+                AccessMonitor x = (AccessMonitor) usage;
+                assert x.object() == node;
+                return false;
+            } else {
+                return true;
+            }
+        }
 
-        EscapeField[] fields(Node node);
+        public abstract EscapeField[] fields(Node node);
 
-        void beforeUpdate(Node node, Node usage);
+        public void beforeUpdate(Node node, Node usage) {
+            if (usage instanceof IsNonNull) {
+                IsNonNull x = (IsNonNull) usage;
+                if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) {
+                    FixedGuard guard = (FixedGuard) x.usages().get(0);
+                    guard.replaceAndDelete(guard.next());
+                }
+                x.delete();
+            } else if (usage instanceof IsType) {
+                IsType x = (IsType) usage;
+                assert x.type() == ((Value) node).exactType();
+                if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) {
+                    FixedGuard guard = (FixedGuard) x.usages().get(0);
+                    guard.replaceAndDelete(guard.next());
+                }
+                x.delete();
+            } else if (usage instanceof AccessMonitor) {
+                AccessMonitor x = (AccessMonitor) usage;
+                x.replaceAndDelete(x.next());
+            }
+        }
 
-        EscapeField updateState(Node node, Node current, Map<Object, EscapeField> fields, Map<EscapeField, Value> fieldState);
+        public abstract int updateState(Node node, Node current, Map<Object, Integer> fieldIndex, Value[] fieldState);
 
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Fri Jul 08 15:00:16 2011 +0200
@@ -106,8 +106,6 @@
     private final Set<Block> blocksOnWorklist = new HashSet<Block>();
     private final Set<Block> blocksVisited = new HashSet<Block>();
 
-    private final boolean createUnwind;
-
     public static final Map<RiMethod, CompilerGraph> cachedGraphs = new WeakHashMap<RiMethod, CompilerGraph>();
 
     /**
@@ -117,10 +115,12 @@
      * @param ir the IR to build the graph into
      * @param graph
      */
-    public GraphBuilderPhase(GraalCompilation compilation, RiMethod method, boolean createUnwind, boolean inline) {
+    public GraphBuilderPhase(GraalCompilation compilation, RiMethod method, boolean inline) {
         super(inline ? "BuildInlineGraph" : "BuildGraph");
         this.compilation = compilation;
 
+        setDetailedName(getName() + " " + method.holder().name() + "." + method.name() + method.signature().asString());
+
         this.runtime = compilation.runtime;
         this.method = method;
         this.stats = compilation.stats;
@@ -128,7 +128,6 @@
         this.stream = new BytecodeStream(method.code());
 
         this.constantPool = runtime.getConstantPool(method);
-        this.createUnwind = createUnwind;
         this.storeResultGraph = GraalOptions.CacheGraphs;
     }
 
@@ -178,19 +177,11 @@
             // 4A.1 add a monitor enter to the start block
             methodSynchronizedObject = synchronizedObject(frameState, method);
             genMonitorEnter(methodSynchronizedObject, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI);
-            // 4A.2 finish the start block
-            finishStartBlock(startBlock);
+        }
 
-            // 4A.3 setup an exception handler to unlock the root method synchronized object
-            unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null);
-        } else {
-            // 4B.1 simply finish the start block
-            finishStartBlock(startBlock);
-
-            if (createUnwind) {
-                unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null);
-            }
-        }
+        // 4B.1 simply finish the start block
+        finishStartBlock(startBlock);
+        unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null);
 
         // 5. SKIPPED: look for intrinsics
 
@@ -732,21 +723,22 @@
         if (entry != null) {
             append(entry);
         } else {
-            frameState.clearStack();
-            frameState.apush(exception);
-            appendGoto(createTarget(unwindBlock(bci), frameState));
+            appendGoto(createTarget(unwindBlock(bci), frameState.duplicateWithException(bci, exception)));
         }
     }
 
     private void genCheckCast() {
         int cpi = stream().readCPI();
         RiType type = constantPool.lookupType(cpi, CHECKCAST);
-        boolean isInitialized = type.isResolved();
-        Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
+        Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, type.isResolved());
         Value object = frameState.apop();
         if (typeInstruction != null) {
-//            append(new FixedGuard(new InstanceOf(typeInstruction, object, graph), graph));
-//            frameState.apush(object);
+//            InstanceOf instanceOf = new InstanceOf(typeInstruction, object, true, graph);
+//            FixedGuard fixedGuard = new FixedGuard(instanceOf, graph);
+//            append(fixedGuard);
+//            CastNode castNode = new CastNode(object.kind, object, graph);
+//            castNode.inputs().add(fixedGuard);
+//            frameState.apush(castNode);
             frameState.apush(new CheckCast(typeInstruction, object, graph));
         } else {
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
@@ -756,11 +748,10 @@
     private void genInstanceOf() {
         int cpi = stream().readCPI();
         RiType type = constantPool.lookupType(cpi, INSTANCEOF);
-        boolean isInitialized = type.isResolved();
-        Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
+        Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, type.isResolved());
         Value object = frameState.apop();
         if (typeInstruction != null) {
-            frameState.ipush(append(new MaterializeNode(new InstanceOf(typeInstruction, object, graph), graph)));
+            frameState.ipush(append(new MaterializeNode(new InstanceOf(typeInstruction, object, false, graph), graph)));
         } else {
             frameState.ipush(appendConstant(CiConstant.INT_0));
         }
@@ -851,7 +842,7 @@
         if (constantValue != null) {
             frameState.push(constantValue.kind.stackKind(), appendConstant(constantValue));
         } else {
-            Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi);
+            Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized);
             CiKind kind = field.kind();
             if (container != null) {
                 LoadField load = new LoadField(container, field, graph);
@@ -865,7 +856,7 @@
 
     private void genPutStatic(int cpi, RiField field) {
         RiType holder = field.holder();
-        Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved() && field.holder().isInitialized(), cpi);
+        Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved() && field.holder().isInitialized());
         Value value = frameState.pop(field.kind().stackKind());
         if (container != null) {
             StoreField store = new StoreField(container, field, value, graph);
@@ -875,7 +866,7 @@
         }
     }
 
-    private Constant genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized, int cpi) {
+    private Constant genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized) {
         if (initialized) {
             return appendConstant(holder.getEncoding(representation));
         } else {
@@ -902,7 +893,7 @@
             // Re-use the same resolution code as for accessing a static field. Even though
             // the result of resolution is not used by the invocation (only the side effect
             // of initialization is required), it can be commoned with static field accesses.
-            genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi);
+            genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized);
         }
         Value[] args = frameState.popArguments(target.signature().argumentSlots(false));
         appendInvoke(INVOKESTATIC, target, args, cpi, constantPool);
@@ -972,6 +963,9 @@
             Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), graph);
             Value result = appendWithBCI(invoke);
             invoke.setExceptionEdge(handleException(null, bci()));
+            if (invoke.exceptionEdge() == null) {
+                TTY.println("no exception edge" + unwindHandler);
+            }
             frameState.pushReturn(resultType, result);
         }
     }
@@ -1256,6 +1250,7 @@
                 } else if (block instanceof DeoptBlock) {
                     createDeoptBlock((DeoptBlock) block);
                 } else {
+                    frameState.setRethrowException(false);
                     iterateBytecodesForBlock(block);
                 }
             }
@@ -1334,14 +1329,18 @@
             assert frameState.stackSize() == 1 : frameState;
 
             Block nextBlock = block.next == null ? unwindBlock(block.deoptBci) : block.next;
-            if (block.handler.catchType().isResolved()) {
+
+
+            RiType catchType = block.handler.catchType();
+            Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, catchType, catchType.isResolved());
+            if (typeInstruction != null) {
                 FixedNode catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState);
                 FixedNode nextDispatch = createTarget(nextBlock, frameState);
-                append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph));
-            } else {
-                Deoptimize deopt = new Deoptimize(DeoptAction.InvalidateRecompile, graph);
-                deopt.setMessage("unresolved " + block.handler.catchType().name());
-                append(deopt);
+                Value exception = frameState.stackAt(0);
+                If ifNode = new If(new InstanceOf(typeInstruction, exception, false, graph), graph);
+                append(ifNode);
+                ifNode.setTrueSuccessor(catchSuccessor);
+                ifNode.setFalseSuccessor(nextDispatch);
             }
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Fri Jul 08 15:00:16 2011 +0200
@@ -31,6 +31,7 @@
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction;
 import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.extensions.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
@@ -41,6 +42,8 @@
 
     public static final HashMap<RiMethod, Integer> methodCount = new HashMap<RiMethod, Integer>();
 
+    private static final int MAX_ITERATIONS = 1000;
+
     private final GraalCompilation compilation;
     private final IR ir;
 
@@ -71,7 +74,7 @@
             }
         }
 
-        for (int iterations = 0; iterations < GraalOptions.MaximumInlineLevel; iterations++) {
+        for (int iterations = 0; iterations < MAX_ITERATIONS; iterations++) {
             Queue<Invoke> queue = newInvokes;
             newInvokes = new ArrayDeque<Invoke>();
             for (Invoke invoke : queue) {
@@ -118,15 +121,20 @@
     private RiMethod inlineInvoke(Invoke invoke, int iterations, float ratio) {
         RiMethod parent = invoke.stateAfter().method();
         RiTypeProfile profile = parent.typeProfile(invoke.bci);
-        if (GraalOptions.Intrinsify && compilation.runtime.intrinsicGraph(invoke.target, invoke.arguments()) != null) {
-            // Always intrinsify.
-            return invoke.target;
+        if (GraalOptions.Intrinsify) {
+            if (GraalOptions.Extend && intrinsicGraph(parent, invoke.bci, invoke.target, invoke.arguments()) != null) {
+                return invoke.target;
+            }
+            if (compilation.runtime.intrinsicGraph(parent, invoke.bci, invoke.target, invoke.arguments()) != null) {
+                // Always intrinsify.
+                return invoke.target;
+            }
         }
         if (!checkInvokeConditions(invoke)) {
             return null;
         }
         if (invoke.opcode() == Bytecodes.INVOKESPECIAL || invoke.target.canBeStaticallyBound()) {
-            if (checkTargetConditions(invoke.target, iterations) && checkSizeConditions(invoke.target, invoke, profile, ratio)) {
+            if (checkTargetConditions(invoke.target, iterations) && checkSizeConditions(parent, iterations, invoke.target, invoke, profile, ratio)) {
                 return invoke.target;
             }
             return null;
@@ -135,7 +143,7 @@
             RiType exact = invoke.receiver().exactType();
             assert exact.isSubtypeOf(invoke.target().holder()) : exact + " subtype of " + invoke.target().holder();
             RiMethod resolved = exact.resolveMethodImpl(invoke.target());
-            if (checkTargetConditions(resolved, iterations) && checkSizeConditions(resolved, invoke, profile, ratio)) {
+            if (checkTargetConditions(resolved, iterations) && checkSizeConditions(parent, iterations, resolved, invoke, profile, ratio)) {
                 return resolved;
             }
             return null;
@@ -153,7 +161,7 @@
 
         RiMethod concrete = holder.uniqueConcreteMethod(invoke.target);
         if (concrete != null) {
-            if (checkTargetConditions(concrete, iterations) && checkSizeConditions(concrete, invoke, profile, ratio)) {
+            if (checkTargetConditions(concrete, iterations) && checkSizeConditions(parent, iterations, concrete, invoke, profile, ratio)) {
                 if (GraalOptions.TraceInlining) {
                     String targetName = CiUtil.format("%H.%n(%p):%r", invoke.target, false);
                     String concreteName = CiUtil.format("%H.%n(%p):%r", concrete, false);
@@ -168,7 +176,7 @@
             if (GraalOptions.InlineWithTypeCheck) {
                 // type check and inlining...
                 concrete = profile.types[0].resolveMethodImpl(invoke.target);
-                if (concrete != null && checkTargetConditions(concrete, iterations) && checkSizeConditions(concrete, invoke, profile, ratio)) {
+                if (concrete != null && checkTargetConditions(concrete, iterations) && checkSizeConditions(parent, iterations, concrete, invoke, profile, ratio)) {
                     IsType isType = new IsType(invoke.receiver(), profile.types[0], compilation.graph);
                     FixedGuard guard = new FixedGuard(isType, graph);
                     assert invoke.predecessors().size() == 1;
@@ -209,6 +217,12 @@
     }
 
     private boolean checkInvokeConditions(Invoke invoke) {
+        if (!invoke.canInline()) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("not inlining %s because the invoke is manually set to be non-inlinable", methodName(invoke.target, invoke));
+            }
+            return false;
+        }
         if (invoke.stateAfter() == null) {
             if (GraalOptions.TraceInlining) {
                 TTY.println("not inlining %s because the invoke has no after state", methodName(invoke.target, invoke));
@@ -266,12 +280,6 @@
             }
             return false;
         }
-        if (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel) {
-            if (GraalOptions.TraceInlining) {
-                TTY.println("not inlining %s because of recursive inlining limit", methodName(method));
-            }
-            return false;
-        }
         return true;
     }
 
@@ -289,7 +297,7 @@
         return true;
     }
 
-    private boolean checkSizeConditions(RiMethod method, Invoke invoke, RiTypeProfile profile, float adjustedRatio) {
+    private boolean checkSizeConditions(RiMethod caller, int iterations, RiMethod method, Invoke invoke, RiTypeProfile profile, float adjustedRatio) {
         int maximumSize = GraalOptions.MaximumTrivialSize;
         float ratio = 0;
         if (profile != null && profile.count > 0) {
@@ -304,19 +312,86 @@
         if (hints != null && hints.contains(invoke)) {
             maximumSize = GraalOptions.MaximumFreqInlineSize;
         }
-        if (method.codeSize() > maximumSize) {
+        if (method.codeSize() > maximumSize || iterations >= GraalOptions.MaximumInlineLevel || (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel)) {
             if (GraalOptions.TraceInlining) {
-                TTY.println("not inlining %s because of code size (size: %d, max size: %d, ratio %5.3f, %s)", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile);
+                TTY.println("not inlining %s because of code size (size: %d, max size: %d, ratio %5.3f, %s) or inling level", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile);
+            }
+            if (GraalOptions.Extend) {
+                boolean newResult = overrideInliningDecision(iterations, caller, invoke.bci, method, false);
+                if (GraalOptions.TraceInlining && newResult) {
+                    TTY.println("overridden inlining decision");
+                }
+                return newResult;
             }
             return false;
         }
         if (GraalOptions.TraceInlining) {
             TTY.println("inlining %s (size: %d, max size: %d, ratio %5.3f, %s)", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile);
         }
+        if (GraalOptions.Extend) {
+            boolean newResult = overrideInliningDecision(iterations, caller, invoke.bci, method, true);
+            if (GraalOptions.TraceInlining && !newResult) {
+                TTY.println("overridden inlining decision");
+            }
+            return newResult;
+        }
         return true;
     }
 
+    public static ThreadLocal<ServiceLoader<InliningGuide>> guideLoader = new ThreadLocal<ServiceLoader<InliningGuide>>();
+
+    private boolean overrideInliningDecision(int iteration, RiMethod caller, int bci, RiMethod target, boolean previousDecision) {
+        ServiceLoader<InliningGuide> serviceLoader = guideLoader.get();
+        if (serviceLoader == null) {
+            serviceLoader = ServiceLoader.load(InliningGuide.class);
+            guideLoader.set(serviceLoader);
+        }
+
+        boolean neverInline = false;
+        boolean alwaysInline = false;
+        for (InliningGuide guide : serviceLoader) {
+            InliningHint hint = guide.getHint(iteration, caller, bci, target);
+
+            if (hint == InliningHint.ALWAYS_INLINE) {
+                alwaysInline = true;
+            } else if (hint == InliningHint.NEVER_INLINE) {
+                neverInline = true;
+            }
+        }
+
+        if (neverInline && alwaysInline) {
+            if (GraalOptions.TraceInlining) {
+                TTY.println("conflicting inlining hints");
+            }
+        } else if (neverInline) {
+            return false;
+        } else if (alwaysInline) {
+            return true;
+        }
+        return previousDecision;
+    }
+
+
+    public static ThreadLocal<ServiceLoader<Intrinsifier>> intrinsicLoader = new ThreadLocal<ServiceLoader<Intrinsifier>>();
+
+    private Graph intrinsicGraph(RiMethod parent, int bci, RiMethod target, List<Value> arguments) {
+        ServiceLoader<Intrinsifier> serviceLoader = intrinsicLoader.get();
+        if (serviceLoader == null) {
+            serviceLoader = ServiceLoader.load(Intrinsifier.class);
+            intrinsicLoader.set(serviceLoader);
+        }
+
+        for (Intrinsifier intrinsifier : serviceLoader) {
+            Graph result = intrinsifier.intrinsicGraph(compilation.runtime, parent, bci, target, arguments);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
     private void inlineMethod(Invoke invoke, RiMethod method) {
+        RiMethod parent = invoke.stateAfter().method();
         FrameState stateAfter = invoke.stateAfter();
         FixedNode exceptionEdge = invoke.exceptionEdge();
         if (exceptionEdge instanceof Placeholder) {
@@ -339,12 +414,11 @@
 
         CompilerGraph graph = null;
         if (GraalOptions.Intrinsify) {
-            graph = (CompilerGraph) compilation.runtime.intrinsicGraph(method, invoke.arguments());
-            if (graph != null && graph.getNodes(Merge.class).iterator().hasNext()) {
-                WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(invoke.graph());
-                checkpoint.setStateAfter(invoke.stateAfter());
-                checkpoint.setNext(invoke.next());
-                invoke.setNext(checkpoint);
+            if (GraalOptions.Extend) {
+                graph = (CompilerGraph) intrinsicGraph(parent, invoke.bci, method, invoke.arguments());
+            }
+            if (graph == null) {
+                graph = (CompilerGraph) compilation.runtime.intrinsicGraph(parent, invoke.bci, method, invoke.arguments());
             }
         }
         if (graph != null) {
@@ -364,7 +438,7 @@
                 TTY.println("Building graph for %s, locals: %d, stack: %d", methodName(method, invoke), method.maxLocals(), method.maxStackSize());
             }
             graph = new CompilerGraph(null);
-            new GraphBuilderPhase(compilation, method, true, true).apply(graph);
+            new GraphBuilderPhase(compilation, method, true).apply(graph);
         }
 
         invoke.inputs().clearAll();
@@ -404,14 +478,25 @@
         } else {
             pred = new Placeholder(compilation.graph);
         }
-        invoke.predecessors().get(0).successors().replace(invoke, pred);
+        invoke.replaceAtPredecessors(pred);
         replacements.put(startNode, pred);
 
         Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements);
 
+        FrameState stateBefore = null;
         for (Node node : duplicates.values()) {
-            if (node instanceof Invoke) {
+            if (node instanceof Invoke && ((Invoke) node).canInline()) {
                 newInvokes.add((Invoke) node);
+            } else if (node instanceof FrameState) {
+                FrameState frameState = (FrameState) node;
+                if (frameState.bci == FrameState.BEFORE_BCI) {
+                    if (stateBefore == null) {
+                        stateBefore = stateAfter.duplicateModified(invoke.bci, false, invoke.kind, parameters);
+                    }
+                    frameState.replaceAndDelete(stateBefore);
+                } else if (frameState.bci == FrameState.AFTER_BCI) {
+                    frameState.replaceAndDelete(stateAfter);
+                }
             }
         }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Fri Jul 08 15:00:16 2011 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
 import com.oracle.max.graal.compiler.observer.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.util.LoopUtil.Loop;
@@ -103,7 +104,7 @@
                         IntegerSub sub = new IntegerSub(kind, c2.init(), c1.init(), graph);
                         IntegerAdd addStride = new IntegerAdd(kind, sub, c1.stride(), graph);
                         IntegerAdd add = new IntegerAdd(kind, c1, addStride, graph);
-                        Phi phi = new Phi(kind, loopBegin, graph); // (gd) assumes order on loopBegin preds - works in collab with graph builder
+                        Phi phi = new Phi(kind, loopBegin, PhiType.Value, graph); // (gd) assumes order on loopBegin preds - works in collab with graph builder
                         phi.addInput(c2.init());
                         phi.addInput(add);
                         c2.replaceAndDelete(phi);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Fri Jul 08 15:00:16 2011 +0200
@@ -57,11 +57,13 @@
     }
 
     private void process(final Block b) {
+
+        final Node anchor = b.javaBlock().createAnchor();
         final CiLoweringTool loweringTool = new CiLoweringTool() {
 
             @Override
             public Node getGuardAnchor() {
-                return b.createAnchor();
+                return anchor;
             }
 
             @Override
@@ -72,19 +74,13 @@
             @Override
             public Node createGuard(Node condition) {
                 Anchor anchor = (Anchor) getGuardAnchor();
-                for (GuardNode guard : anchor.happensAfterGuards()) {
-                    if (guard.node().valueEqual(condition)) {
-                        condition.delete();
-                        return guard;
-                    }
-                }
-                GuardNode newGuard = new GuardNode(anchor.graph());
+                GuardNode newGuard = new GuardNode((BooleanNode) condition, anchor.graph());
                 newGuard.setAnchor(anchor);
-                newGuard.setNode((BooleanNode) condition);
                 return newGuard;
             }
         };
 
+
         // Lower the instructions of this block.
         for (final Node n : b.getInstructions()) {
             if (n instanceof FixedNode) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Fri Jul 08 15:00:16 2011 +0200
@@ -28,6 +28,7 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
@@ -155,8 +156,7 @@
                 assert phi.valueCount() <= phi.merge().endCount();
                 return original;
             } else {
-                Phi phi = new Phi(CiKind.Illegal, m, m.graph());
-                phi.makeDead(); // Phi does not produce a value, it is only a memory phi.
+                Phi phi = new Phi(CiKind.Illegal, m, PhiType.Memory, m.graph());
                 for (int i = 0; i < mergeOperationCount + 1; ++i) {
                     phi.addInput(original);
                 }
@@ -198,7 +198,7 @@
             }
 
             // Create dependency on previous write to same location.
-            node.inputs().variablePart().add(getLocationForWrite(node));
+            node.addDependency(getLocationForWrite(node));
 
             locationForWrite.put(location, node);
             locationForRead.put(location, node);
@@ -220,7 +220,7 @@
             }
 
             // Create dependency on previous node that creates the memory state for this location.
-            node.inputs().variablePart().add(getLocationForRead(node));
+            node.addDependency(getLocationForRead(node));
         }
 
         public Node getLocationForRead(ReadNode node) {
@@ -315,6 +315,8 @@
             LoopBegin begin = end.loopBegin();
             Block beginBlock = nodeMap.get(begin);
             MemoryMap memoryMap = memoryMaps[beginBlock.blockID()];
+            assert memoryMap != null : beginBlock.name();
+            assert memoryMap.getLoopEntryMap() != null;
             memoryMap.getLoopEntryMap().resetMergeOperationCount();
             memoryMap.getLoopEntryMap().mergeWith(map, beginBlock);
             Node loopCheckPoint = memoryMap.getLoopCheckPoint();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Fri Jul 08 15:00:16 2011 +0200
@@ -30,12 +30,14 @@
 public abstract class Phase {
 
     private final String name;
+    private String detailedName;
     private static final ThreadLocal<Phase> currentPhase = new ThreadLocal<Phase>();
     private final boolean shouldVerify;
 
     public Phase() {
         this.name = this.getClass().getSimpleName();
         this.shouldVerify = true;
+        this.detailedName = name;
     }
 
     public Phase(String name) {
@@ -45,6 +47,11 @@
     public Phase(String name, boolean shouldVerify) {
         this.name = name;
         this.shouldVerify = shouldVerify;
+        this.detailedName = name;
+    }
+
+    protected void setDetailedName(String detailedName) {
+        this.detailedName = detailedName;
     }
 
     public final void apply(Graph graph) {
@@ -71,13 +78,13 @@
         } catch (AssertionError t) {
             GraalCompilation compilation = GraalCompilation.compilation();
             if (compilation.compiler.isObserved() && plotOnError) {
-                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + getName(), graph, true, false, true));
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + detailedName, graph, true, false, true));
             }
             throw t;
         } catch (RuntimeException t) {
             GraalCompilation compilation = GraalCompilation.compilation();
             if (compilation.compiler.isObserved() && plotOnError) {
-                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + getName(), graph, true, false, true));
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + detailedName, graph, true, false, true));
             }
             throw t;
         }
@@ -98,7 +105,7 @@
         }
         GraalCompilation compilation = GraalCompilation.compilation();
         if (compilation.compiler.isObserved() && this.getClass() != IdentifyBlocksPhase.class) {
-            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + getName(), graph, true, false));
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + detailedName, graph, true, false));
         }
 
         assert !shouldVerify || graph.verify();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java	Fri Jul 08 15:00:16 2011 +0200
@@ -35,8 +35,8 @@
     @Override
     protected void run(Graph graph) {
         for (ReadNode n : graph.getNodes(ReadNode.class)) {
-            if (n.inputs().variablePart().size() > 0) {
-                Node memoryInput = n.inputs().variablePart().get(0);
+            if (n.dependencies().size() > 0) {
+                Node memoryInput = n.dependencies().get(0);
                 if (memoryInput instanceof WriteNode) {
                     WriteNode other = (WriteNode) memoryInput;
                     if (other.object() == n.object() && other.location() == n.location()) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Fri Jul 08 15:00:16 2011 +0200
@@ -38,6 +38,8 @@
     private Block javaBlock;
     private final List<Block> dominators = new ArrayList<Block>();
     private Anchor anchor;
+    private int loopDepth = 0;
+    private int loopIndex = -1;
 
     private Node firstNode;
     private Node lastNode;
@@ -63,6 +65,22 @@
         return lastNode;
     }
 
+    public int loopDepth() {
+        return loopDepth;
+    }
+
+    public void setLoopDepth(int i) {
+        loopDepth = i;
+    }
+
+    public int loopIndex() {
+        return loopIndex;
+    }
+
+    public void setLoopIndex(int i) {
+        loopIndex = i;
+    }
+
     public Anchor createAnchor() {
         if (anchor == null) {
             if (firstNode instanceof Anchor) {
@@ -77,14 +95,14 @@
                     firstNode.graph().start().setNext(a);
                     this.anchor = a;
                 }
-            } else if (firstNode instanceof Merge) {
-                Merge merge = (Merge) firstNode;
-                if (merge.next() instanceof Anchor) {
-                    this.anchor = (Anchor) merge.next();
+            } else if (firstNode instanceof Merge || firstNode instanceof ExceptionObject) {
+                FixedNodeWithNext fixedNode = (FixedNodeWithNext) firstNode;
+                if (fixedNode.next() instanceof Anchor) {
+                    this.anchor = (Anchor) fixedNode.next();
                 } else {
                     Anchor a = new Anchor(firstNode.graph());
-                    a.setNext(merge.next());
-                    merge.setNext(a);
+                    a.setNext(fixedNode.next());
+                    fixedNode.setNext(a);
                     this.anchor = a;
                 }
             } else {
@@ -175,6 +193,10 @@
         return firstNode instanceof LoopBegin;
     }
 
+    public boolean isLoopEnd() {
+        return lastNode instanceof LoopEnd;
+    }
+
     public Block dominator() {
         return dominator;
     }
@@ -224,4 +246,8 @@
             }
         }
     }
+
+    public String name() {
+        return "B" + blockID;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Fri Jul 08 15:00:16 2011 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.phases.*;
@@ -36,6 +37,7 @@
     private NodeMap<Block> nodeToBlock;
     private Graph graph;
     private boolean scheduleAllNodes;
+    private int loopCount;
 
     public IdentifyBlocksPhase(boolean scheduleAllNodes) {
         super(scheduleAllNodes ? "FullSchedule" : "PartSchedule", false);
@@ -64,6 +66,10 @@
         return b;
     }
 
+    public int loopCount() {
+        return loopCount;
+    }
+
     private Block assignBlockNew(Node n, Block b) {
         if (b == null) {
             b = createBlock();
@@ -71,6 +77,20 @@
 
         assert nodeToBlock.get(n) == null;
         nodeToBlock.set(n, b);
+
+        if (n instanceof Merge) {
+            for (Node usage : n.usages()) {
+
+                if (usage instanceof Phi) {
+                    nodeToBlock.set(usage, b);
+                }
+
+                if (usage instanceof LoopCounter) {
+                    nodeToBlock.set(usage, b);
+                }
+
+            }
+        }
         if (b.lastNode() == null) {
             b.setFirstNode(n);
             b.setLastNode(n);
@@ -154,17 +174,7 @@
 
 
         if (scheduleAllNodes) {
-
-            // Add successors of loop end nodes. Makes the graph cyclic.
-            for (Block block : blocks) {
-                Node n = block.lastNode();
-                if (n instanceof LoopEnd) {
-                    LoopEnd loopEnd = (LoopEnd) n;
-                    assert loopEnd.loopBegin() != null;
-                    block.addSuccessor(nodeToBlock.get(loopEnd.loopBegin()));
-                }
-            }
-
+            computeLoopInformation(); // Will make the graph cyclic.
             assignLatestPossibleBlockToNodes();
             sortNodesWithinBlocks();
         } else {
@@ -172,6 +182,52 @@
         }
     }
 
+    private void computeLoopInformation() {
+
+        // Add successors of loop end nodes. Makes the graph cyclic.
+        for (Block block : blocks) {
+            Node n = block.lastNode();
+            if (n instanceof LoopEnd) {
+                LoopEnd loopEnd = (LoopEnd) n;
+                assert loopEnd.loopBegin() != null;
+                Block loopBeginBlock = nodeToBlock.get(loopEnd.loopBegin());
+                block.addSuccessor(loopBeginBlock);
+                BitMap map = new BitMap(blocks.size());
+                markBlocks(block, loopBeginBlock, map, loopCount++, block.loopDepth());
+                assert loopBeginBlock.loopDepth() == block.loopDepth() && loopBeginBlock.loopIndex() == block.loopIndex();
+            }
+        }
+
+//        for (Block block : blocks) {
+//            TTY.println("Block B" + block.blockID() + " loopIndex=" + block.loopIndex() + ", loopDepth=" + block.loopDepth());
+//        }
+    }
+
+    private void markBlocks(Block block, Block endBlock, BitMap map, int loopIndex, int initialDepth) {
+        if (map.get(block.blockID())) {
+            return;
+        }
+
+        map.set(block.blockID());
+        if (block.loopDepth() <= initialDepth) {
+            assert block.loopDepth() == initialDepth;
+            block.setLoopIndex(loopIndex);
+        }
+        block.setLoopDepth(block.loopDepth() + 1);
+
+        if (block == endBlock) {
+            return;
+        }
+
+        for (Block pred : block.getPredecessors()) {
+            markBlocks(pred, endBlock, map, loopIndex, initialDepth);
+        }
+
+        if (block.isLoopHeader()) {
+            markBlocks(nodeToBlock.get(((LoopBegin) block.firstNode()).loopEnd()), endBlock, map, loopIndex, initialDepth);
+        }
+    }
+
     private void computeJavaBlocks() {
 
         for (Block b : blocks) {
@@ -240,16 +296,6 @@
 
         assert !n.isDeleted();
 
-        if (n instanceof Phi) {
-            Block block = nodeToBlock.get(((Phi) n).merge());
-            nodeToBlock.set(n, block);
-        }
-
-        if (n instanceof LoopCounter) {
-            Block block = nodeToBlock.get(((LoopCounter) n).loopBegin());
-            nodeToBlock.set(n, block);
-        }
-
         Block prevBlock = nodeToBlock.get(n);
         if (prevBlock != null) {
             return prevBlock;
@@ -267,10 +313,11 @@
                 assert mergeBlock != null : "no block for merge " + merge.id();
                 for (int i = 0; i < phi.valueCount(); ++i) {
                     if (phi.valueAt(i) == n) {
-                        if (mergeBlock.getPredecessors().size() == 0) {
+                        if (mergeBlock.getPredecessors().size() <= i) {
                             TTY.println(merge.toString());
                             TTY.println(phi.toString());
                             TTY.println(merge.phiPredecessors().toString());
+                            TTY.println(phi.inputs().toString());
                             TTY.println("value count: " + phi.valueCount());
                         }
                         block = getCommonDominator(block, mergeBlock.getPredecessors().get(i));
@@ -295,13 +342,76 @@
             }
         }
 
-        nodeToBlock.set(n, block);
+
         if (block != null) {
+            if (GraalOptions.OptOptimisticSchedule) {
+                block = scheduleOutOfLoops(n, block);
+            }
+            nodeToBlock.set(n, block);
             block.getInstructions().add(n);
         }
         return block;
     }
 
+    private Block scheduleOutOfLoops(Node n, Block latestBlock) {
+        Block cur = latestBlock;
+        while (cur.loopDepth() != 0) {
+            if (cur.isLoopHeader()) {
+                assert cur.getPredecessors().size() == 2 : cur.getPredecessors().size();
+                if (canSchedule(n, cur.getPredecessors().get(0))) {
+                   // TTY.println("can schedule out of loop!" + n);
+                    return scheduleOutOfLoops(n, cur.getPredecessors().get(0));
+                } else {
+                    break;
+                }
+            }
+            Block prev = cur;
+            cur = cur.dominator();
+
+            // This must be a loop exit.
+            if (cur.loopDepth() > prev.loopDepth()) {
+//                TTY.println("break out because of different loop depth");
+                break;
+            }
+        }
+        return latestBlock;
+    }
+
+    private boolean canSchedule(Node n, Block block) {
+        Set<Block> allowedBlocks = new HashSet<Block>();
+        Block cur = block;
+        while (cur != null) {
+            allowedBlocks.add(cur);
+            cur = cur.dominator();
+        }
+        // Now we know the allowed blocks for inputs and predecessors.
+        return checkNodesAbove(allowedBlocks, n);
+    }
+
+    private boolean checkNodesAbove(Set<Block> allowedBlocks, Node n) {
+        if (n == null) {
+            return true;
+        }
+
+        if (nodeToBlock.get(n) != null) {
+            return allowedBlocks.contains(nodeToBlock.get(n));
+        } else {
+            assert !(n instanceof Phi) : ((Phi) n).merge();
+            for (Node input : n.inputs()) {
+                if (!checkNodesAbove(allowedBlocks, input)) {
+                    return false;
+                }
+            }
+            for (Node pred : n.predecessors()) {
+                if (!checkNodesAbove(allowedBlocks, pred)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+
     private Block getCommonDominator(Block a, Block b) {
         if (a == null) {
             return b;
@@ -324,15 +434,11 @@
         List<Node> sortedInstructions = new ArrayList<Node>(instructions.size() + 2);
 
         assert !map.isMarked(b.firstNode()) && nodeToBlock.get(b.firstNode()) == b;
-//        assert !instructions.contains(b.firstNode());
-//        assert !instructions.contains(b.lastNode());
         assert !map.isMarked(b.lastNode()) && nodeToBlock.get(b.lastNode()) == b;
 
-        //addToSorting(b, b.firstNode(), sortedInstructions, map);
         for (Node i : instructions) {
             addToSorting(b, i, sortedInstructions, map);
         }
-        //addToSorting(b, b.lastNode(), sortedInstructions, map);
 
         // Make sure that last node gets really last (i.e. when a frame state successor hangs off it).
         Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1);
@@ -367,10 +473,10 @@
         }
 
         if (i instanceof WriteNode) {
-            // Make sure every ReadNode that is connected to the same memory state is executed before every write node.
+            // TODO(tw): Make sure every ReadNode that is connected to the same memory state is executed before every write node.
             WriteNode wn = (WriteNode) i;
             // TODO: Iterate over variablePart.
-            wn.inputs().variablePart();
+//            wn.variableInputs();
         }
 
         FrameState state = null;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Fri Jul 08 15:00:16 2011 +0200
@@ -556,6 +556,8 @@
                     case AE : acond = ConditionFlag.aboveEqual; break;
                     case AT : acond = ConditionFlag.above; break;
                     case BT : acond = ConditionFlag.below; break;
+                    case OF : acond = ConditionFlag.overflow; break;
+                    case NOF : acond = ConditionFlag.noOverflow; break;
                     default : throw Util.shouldNotReachHere();
                 }
                 // Checkstyle: on
@@ -1300,11 +1302,11 @@
                     default      : throw Util.shouldNotReachHere();
                 }
             } else {
-                throw Util.shouldNotReachHere();
+                throw Util.shouldNotReachHere("opr1=" + opr1.toString() + " opr2=" + opr2);
             }
 
         } else {
-            throw Util.shouldNotReachHere(opr1.toString() + " opr2 = " + opr2);
+            throw Util.shouldNotReachHere("opr1=" + opr1.toString() + " opr2=" + opr2);
         }
         // Checkstyle: on
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Fri Jul 08 15:00:16 2011 +0200
@@ -33,9 +33,6 @@
 import com.oracle.max.graal.compiler.util.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
-import com.sun.cri.ri.*;
-import com.sun.cri.ri.RiType.*;
-import com.sun.cri.xir.*;
 
 /**
  * This class implements the X86-specific portion of the LIR generator.
@@ -367,7 +364,7 @@
             return;
         }
 
-        assert Util.archKindsEqual(x.x().kind, x.kind) && Util.archKindsEqual(x.y().kind, x.kind) : "wrong parameter types: " + Bytecodes.nameOf(x.opcode);
+        assert Util.archKindsEqual(x.x().kind, x.kind) && Util.archKindsEqual(x.y().kind, x.kind) : "wrong parameter types: " + Bytecodes.nameOf(x.opcode) + ", x: " + x.x() + ", y: " + x.y() + ", kind: " + x.kind;
         switch (x.kind) {
             case Float:
             case Double:
@@ -466,30 +463,11 @@
     }
 
     @Override
-    public void visitExceptionDispatch(ExceptionDispatch x) {
-        // TODO ls: this needs some more work...
-
-        RiType riType = x.catchType();
-        assert riType.isResolved();
-
-        XirArgument obj = toXirArgument(x.exception());
-        XirArgument clazz = toXirArgument(riType.getEncoding(Representation.ObjectHub));
-        XirSnippet snippet = xir.genInstanceOf(site(x), obj, clazz, riType);
-        emitXir(snippet, x, stateFor(x), null, false);
-
-        LIRXirInstruction instr = (LIRXirInstruction) lir.instructionsList().get(lir.instructionsList().size() - 1);
-        instr.setTrueSuccessor(getLIRBlock(x.catchSuccessor()));
-        lir.jump(getLIRBlock(x.otherSuccessor()));
-    }
-
-    @Override
     public void visitLoopBegin(LoopBegin x) {
-
     }
 
     @Override
     public void visitValueAnchor(ValueAnchor valueAnchor) {
         // nothing to do for ValueAnchors
     }
-
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java	Fri Jul 08 15:00:16 2011 +0200
@@ -27,6 +27,7 @@
 
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
 import com.oracle.max.graal.compiler.observer.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
@@ -232,7 +233,7 @@
                                     colorQueue.offer(color);
                                     continue;
                                 }
-                                Phi phi = new Phi(((Value) node).kind, lambda.merge(color), node.graph());
+                                Phi phi = new Phi(((Value) node).kind, lambda.merge(color), PhiType.Value, node.graph());
                                 for (T parentColor : parentColors) {
                                     Node input = newNodes.get(parentColor);
                                     phi.addInput(input);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java	Fri Jul 08 15:00:16 2011 +0200
@@ -27,6 +27,7 @@
 
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.*;
 import com.oracle.max.graal.compiler.observer.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.util.GraphUtil.ColorSplitingLambda;
@@ -185,7 +186,7 @@
             for (Node usage : n.dataUsages()) {
                 if (usage instanceof Phi) { // filter out data graph cycles
                     Phi phi = (Phi) usage;
-                    if (!phi.isDead()) {
+                    if (phi.type() == PhiType.Value) {
                         Merge merge = phi.merge();
                         if (merge instanceof LoopBegin) {
                             LoopBegin phiLoop = (LoopBegin) merge;
@@ -205,7 +206,7 @@
             inOrBefore.mark(n);
             if (n instanceof Phi) { // filter out data graph cycles
                 Phi phi = (Phi) n;
-                if (!phi.isDead()) {
+                if (phi.type() == PhiType.Value) {
                     int backIndex = -1;
                     Merge merge = phi.merge();
                     if (!loopNodes.isMarked(merge) && merge instanceof LoopBegin) {
@@ -524,7 +525,7 @@
                     values.add(valueAt);
                 }
                 if (createPhi) {
-                    Phi phi = new Phi(kind, merge, merge.graph());
+                    Phi phi = new Phi(kind, merge, PhiType.Value, merge.graph());
                     valueMap.set(point, phi);
                     for (EndNode end : merge.cfgPredecessors()) {
                         phi.addInput(getValueAt(colors.get(end), valueMap, kind));
@@ -759,14 +760,12 @@
             for (Node usage : n.usages()) {
                 if (usage instanceof Phi) { // filter out data graph cycles
                     Phi phi = (Phi) usage;
-                    if (!phi.isDead()) {
-                        Merge merge = phi.merge();
-                        if (merge instanceof LoopBegin) {
-                            LoopBegin phiLoop = (LoopBegin) merge;
-                            int backIndex = phiLoop.phiPredecessorIndex(phiLoop.loopEnd());
-                            if (phi.valueAt(backIndex) == n) {
-                                continue;
-                            }
+                    Merge merge = phi.merge();
+                    if (merge instanceof LoopBegin) {
+                        LoopBegin phiLoop = (LoopBegin) merge;
+                        int backIndex = phiLoop.phiPredecessorIndex(phiLoop.loopEnd());
+                        if (phi.valueAt(backIndex) == n) {
+                            continue;
                         }
                     }
                 }
@@ -789,7 +788,7 @@
             }
             if (n instanceof Phi) { // filter out data graph cycles
                 Phi phi = (Phi) n;
-                if (!phi.isDead()) {
+                if (phi.type() == PhiType.Value) {
                     int backIndex = -1;
                     Merge merge = phi.merge();
                     if (!loopNodes.isNew(merge) && !loopNodes.isMarked(merge) && merge instanceof LoopBegin) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Fri Jul 08 15:00:16 2011 +0200
@@ -29,6 +29,7 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -49,10 +50,13 @@
 
     protected final int locksSize;
 
-    private final boolean rethrowException;
+    private boolean rethrowException;
 
     private static final int SUCCESSOR_COUNT = 0;
 
+    public static final int BEFORE_BCI = -2;
+    public static final int AFTER_BCI = -3;
+
     @Override
     protected int inputCount() {
         return super.inputCount() + localsSize + stackSize + locksSize;
@@ -125,6 +129,23 @@
         return method;
     }
 
+    public void addVirtualObjectMapping(Node virtualObject) {
+        assert virtualObject instanceof VirtualObjectField || virtualObject instanceof Phi : virtualObject;
+        variableInputs().add(virtualObject);
+    }
+
+    public int virtualObjectMappingCount() {
+        return variableInputs().size();
+    }
+
+    public Node virtualObjectMappingAt(int i) {
+        return variableInputs().get(i);
+    }
+
+    public List<Node> virtualObjectMappings() {
+        return variableInputs();
+    }
+
     /**
      * Gets a copy of this frame state.
      */
@@ -135,6 +156,7 @@
     public FrameState duplicate(int bci, boolean duplicateOuter) {
         FrameState other = new FrameState(method, bci, localsSize, stackSize, locksSize, rethrowException, graph());
         other.inputs().setAll(inputs());
+        other.variableInputs().addAll(variableInputs());
         FrameState outerFrameState = outerFrameState();
         if (duplicateOuter && outerFrameState != null) {
             outerFrameState = outerFrameState.duplicate(outerFrameState.bci, duplicateOuter);
@@ -170,6 +192,7 @@
         for (int i = 0; i < locksSize; i++) {
             other.setValueAt(localsSize + other.stackSize + i, lockAt(i));
         }
+        other.variableInputs().addAll(variableInputs());
         other.setOuterFrameState(outerFrameState());
         return other;
     }
@@ -322,7 +345,7 @@
                     return phi;
                 }
             }
-            Phi phi = new Phi(p.kind, block, graph());
+            Phi phi = new Phi(p.kind, block, PhiType.Value, graph());
             setValueAt(localsSize + i, phi);
             return phi;
         }
@@ -342,7 +365,7 @@
                 return phi;
             }
         }
-        Phi phi = new Phi(p.kind, block, graph());
+        Phi phi = new Phi(p.kind, block, PhiType.Value, graph());
         storeLocal(i, phi);
         return phi;
     }
@@ -390,11 +413,9 @@
                 Value y = other.valueAt(i);
                 if (x != y || ((x instanceof Phi) && ((Phi) x).merge() == block)) {
                     if (typeMismatch(x, y)) {
-                        if (x instanceof Phi) {
-                            Phi phi = (Phi) x;
-                            if (phi.merge() == block) {
-                                phi.makeDead();
-                            }
+                        if ((x instanceof Phi) && ((Phi) x).merge() == block) {
+                            x.replaceAtUsages(null);
+                            x.delete();
                         }
                         setValueAt(i, null);
                         continue;
@@ -512,30 +533,83 @@
      * @param proc the call back called to process each live value traversed
      */
     public void forEachLiveStateValue(ValueProcedure proc) {
-        for (int i = 0; i < valuesSize(); i++) {
-            Value value = valueAt(i);
-            visitLiveStateValue(value, proc);
-        }
-        if (outerFrameState() != null) {
-            outerFrameState().forEachLiveStateValue(proc);
-        }
-    }
+        HashSet<VirtualObject> vobjs = null;
+        FrameState current = this;
+        do {
+            for (int i = 0; i < current.valuesSize(); i++) {
+                Value value = current.valueAt(i);
+                if (value instanceof VirtualObject) {
+                    if (vobjs == null) {
+                        vobjs = new HashSet<VirtualObject>();
+                    }
+                    vobjs.add((VirtualObject) value);
+                } else if (value != null) {
+                    proc.doValue(value);
+                }
+            }
+            current = current.outerFrameState();
+        } while (current != null);
+
+        if (vobjs != null) {
+            // collect all VirtualObjectField instances:
+            HashMap<VirtualObject, VirtualObjectField> objectStates = new HashMap<VirtualObject, VirtualObjectField>();
+            current = this;
+            do {
+                for (int i = 0; i < current.virtualObjectMappingCount(); i++) {
+                    VirtualObjectField field = (VirtualObjectField) current.virtualObjectMappingAt(i);
+                    // null states occur for objects with 0 fields
+                    if (field != null && !objectStates.containsKey(field.object())) {
+                        objectStates.put(field.object(), field);
+                    }
+                }
+                current = current.outerFrameState();
+            } while (current != null);
 
-    private void visitLiveStateValue(Value value, ValueProcedure proc) {
-        if (value != null) {
-            if (value instanceof VirtualObject) {
-                HashSet<Object> fields = new HashSet<Object>();
-                VirtualObject obj = (VirtualObject) value;
-                do {
-                    if (!fields.contains(obj.field().representation())) {
-                        fields.add(obj.field().representation());
-                        visitLiveStateValue(obj.input(), proc);
+            do {
+                HashSet<VirtualObject> vobjsCopy = new HashSet<VirtualObject>(vobjs);
+                for (VirtualObject vobj : vobjsCopy) {
+                    if (vobj.fields().length > 0) {
+                        boolean[] fieldState = new boolean[vobj.fields().length];
+                        FloatingNode currentField = objectStates.get(vobj);
+                        assert currentField != null : this;
+                        do {
+                            if (currentField instanceof VirtualObjectField) {
+                                int index = ((VirtualObjectField) currentField).index();
+                                Value value = ((VirtualObjectField) currentField).input();
+                                if (!fieldState[index]) {
+                                    fieldState[index] = true;
+                                    if (value instanceof VirtualObject) {
+                                        vobjs.add((VirtualObject) value);
+                                    } else {
+                                        proc.doValue(value);
+                                    }
+                                }
+                                currentField = ((VirtualObjectField) currentField).lastState();
+                            } else {
+                                assert currentField instanceof Phi : currentField;
+                                currentField = (FloatingNode) ((Phi) currentField).valueAt(0);
+                            }
+                        } while (currentField != null);
                     }
-                    obj = obj.object();
-                } while (obj != null);
-            } else {
-                proc.doValue(value);
+                    vobjs.remove(vobj);
+                }
+            } while (!vobjs.isEmpty());
+            if (!vobjs.isEmpty()) {
+                for (VirtualObject obj : vobjs) {
+                    TTY.println("+" + obj);
+                }
+                for (Node vobj : variableInputs()) {
+                    if (vobj instanceof VirtualObjectField) {
+                        TTY.println("-" + ((VirtualObjectField) vobj).object());
+                    } else {
+                        TTY.println("-" + vobj);
+                    }
+                }
+                for (Node n : this.usages()) {
+                    TTY.println("usage: " + n);
+                }
             }
+            assert vobjs.isEmpty() : "at FrameState " + this;
         }
     }
 
@@ -620,6 +694,11 @@
     }
 
     @Override
+    public void setRethrowException(boolean b) {
+        rethrowException = b;
+    }
+
+    @Override
     public Node copy(Graph into) {
         return new FrameState(method, bci, localsSize, stackSize, locksSize, rethrowException, into);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateAccess.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateAccess.java	Fri Jul 08 15:00:16 2011 +0200
@@ -34,6 +34,8 @@
 
     int locksSize();
 
+    boolean rethrowException();
+
     Value valueAt(int i);
 
     Value localAt(int i);
@@ -44,6 +46,8 @@
 
     void setValueAt(int j, Value v);
 
+    void setRethrowException(boolean b);
+
     Value outerFrameState();
 
     FrameState duplicateWithException(int bci, Value exceptionObject);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java	Fri Jul 08 15:00:16 2011 +0200
@@ -28,6 +28,7 @@
 import java.util.*;
 
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -42,6 +43,7 @@
     private final ArrayList<Value> locks;
 
     private int stackIndex;
+    private boolean rethrowException;
 
     private final RiMethod method;
 
@@ -101,10 +103,11 @@
         for (int i = 0; i < other.locksSize(); i++) {
             locks.add(other.lockAt(i));
         }
+        this.rethrowException = other.rethrowException();
     }
 
     public FrameState create(int bci) {
-        return new FrameState(method, bci, locals, stack, stackIndex, locks, false, graph);
+        return new FrameState(method, bci, locals, stack, stackIndex, locks, rethrowException, graph);
     }
 
     public FrameState duplicateWithException(int bci, Value exceptionObject) {
@@ -332,8 +335,11 @@
     public Value loadLocal(int i) {
         Value x = locals[i];
         if (x != null) {
-            if (x instanceof Phi && ((Phi) x).isDead()) {
-                return null;
+            if (x instanceof Phi) {
+                assert ((Phi) x).type() == PhiType.Value;
+                if (x.isDeleted()) {
+                    return null;
+                }
             }
             assert x.kind.isSingleWord() || locals[i + 1] == null || locals[i + 1] instanceof Phi;
         }
@@ -513,4 +519,14 @@
         frameState.setOuterFrameState(outerFrameState());
         return frameState;
     }
+
+    @Override
+    public boolean rethrowException() {
+        return rethrowException;
+    }
+
+    @Override
+    public void setRethrowException(boolean b) {
+        rethrowException = b;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/FrameModifier.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public interface FrameModifier {
+    CiFrame getFrame(RiRuntime runtime, CiFrame frame);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/InliningExample.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+
+public class InliningExample {
+
+    public static void run() {
+        System.out.println(test());
+        long start = System.currentTimeMillis();
+        System.out.println(testFib());
+        System.out.println(System.currentTimeMillis() - start);
+    }
+
+    private static int test() {
+        return alwaysInline(30);
+    }
+
+    public static int testFib() {
+        int sum = 0;
+        for (int i = 0; i < 10000000; ++i) {
+            sum += fib(5);
+        }
+        return sum;
+    }
+
+    public static int alwaysInline(int value) {
+        if (value == 0) {
+            return neverInline(value);
+        }
+        return alwaysInline(value - 1);
+    }
+
+    public static int neverInline(int value) {
+        if (value == 0) {
+            return 0;
+        }
+        return neverInline(value - 1);
+    }
+
+    public static int fib(int val) {
+        if (val == 0 || val == 1) {
+            return 1;
+        }
+        return fib(val - 1) + fib(val - 2);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/InliningGuide.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+import com.sun.cri.ri.*;
+
+
+public interface InliningGuide {
+    InliningHint getHint(int depth, RiMethod caller, int bci, RiMethod target);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/InliningHint.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+
+public enum InliningHint {
+    NONE,
+    ALWAYS_INLINE,
+    NEVER_INLINE
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/Intrinsifier.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ri.*;
+
+
+public interface Intrinsifier {
+    Graph intrinsicGraph(RiRuntime runtime, RiMethod caller, int bci, RiMethod method, List<? extends Node> parameters);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/Optimizer.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ri.*;
+
+
+public interface Optimizer {
+    void optimize(RiRuntime runtime, Graph graph);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.checkstyle	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
+  <local-check-config name="C1X Checkstyle checks" location=".checkstyle_checks.xml" type="project" description="">
+    <additional-data name="protect-config-file" value="false"/>
+  </local-check-config>
+  <fileset name="all" enabled="true" check-config-name="C1X Checkstyle checks" local="true">
+    <file-match-pattern match-pattern="." include-pattern="true"/>
+  </fileset>
+</fileset-config>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.checkstyle_checks.xml	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!--
+    This configuration file was written by the eclipse-cs plugin configuration editor
+-->
+<!--
+    Checkstyle-Configuration: C1X Checkstyle checks
+    Description: none
+-->
+<module name="Checker">
+  <property name="severity" value="warning"/>
+  <module name="TreeWalker">
+    <property name="tabWidth" value="4"/>
+    <module name="FileContentsHolder"/>
+    <module name="JavadocStyle">
+      <property name="checkHtml" value="false"/>
+    </module>
+    <module name="LocalFinalVariableName"/>
+    <module name="LocalVariableName"/>
+    <module name="MemberName">
+      <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
+    </module>
+    <module name="MethodName">
+      <property name="format" value="^[a-z][a-z_A-Z0-9]*$"/>
+    </module>
+    <module name="PackageName"/>
+    <module name="ParameterName"/>
+    <module name="TypeName">
+      <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
+    </module>
+    <module name="RedundantImport"/>
+    <module name="LineLength">
+      <property name="max" value="250"/>
+    </module>
+    <module name="MethodParamPad"/>
+    <module name="NoWhitespaceAfter">
+      <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
+    </module>
+    <module name="NoWhitespaceBefore">
+      <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
+    </module>
+    <module name="ParenPad"/>
+    <module name="TypecastParenPad">
+      <property name="tokens" value="RPAREN,TYPECAST"/>
+    </module>
+    <module name="WhitespaceAfter"/>
+    <module name="WhitespaceAround">
+      <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
+    </module>
+    <module name="RedundantModifier"/>
+    <module name="AvoidNestedBlocks">
+      <property name="allowInSwitchCase" value="true"/>
+    </module>
+    <module name="EmptyBlock">
+      <property name="option" value="text"/>
+      <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
+    </module>
+    <module name="LeftCurly"/>
+    <module name="NeedBraces"/>
+    <module name="RightCurly"/>
+    <module name="DoubleCheckedLocking">
+      <property name="severity" value="error"/>
+    </module>
+    <module name="EmptyStatement"/>
+    <module name="HiddenField">
+      <property name="severity" value="ignore"/>
+      <property name="ignoreConstructorParameter" value="true"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="FinalClass"/>
+    <module name="HideUtilityClassConstructor">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="ArrayTypeStyle"/>
+    <module name="UpperEll"/>
+    <module name="FallThrough"/>
+    <module name="FinalLocalVariable">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="MultipleVariableDeclarations"/>
+    <module name="StringLiteralEquality">
+      <property name="severity" value="error"/>
+    </module>
+    <module name="SuperFinalize"/>
+    <module name="UnnecessaryParentheses">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="Indentation">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="StaticVariableName">
+      <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
+    </module>
+    <module name="EmptyForInitializerPad"/>
+    <module name="EmptyForIteratorPad"/>
+    <module name="ModifierOrder"/>
+    <module name="DefaultComesLast"/>
+    <module name="InnerAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="JUnitTestCase"/>
+    <module name="ModifiedControlVariable"/>
+    <module name="MutableException"/>
+    <module name="ParameterAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value="\s$"/>
+      <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value=" ,"/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
+    </module>
+  </module>
+  <module name="RegexpHeader">
+    <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
+  </module>
+  <module name="FileTabCharacter">
+    <property name="severity" value="error"/>
+  </module>
+  <module name="NewlineAtEndOfFile">
+    <property name="lineSeparator" value="lf"/>
+  </module>
+  <module name="Translation"/>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
+    <property name="checkFormat" value="ConstantNameCheck"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
+    <property name="checkFormat" value="MethodName"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
+    <property name="checkFormat" value="ParameterAssignment"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
+    <property name="checkFormat" value="FinalLocalVariable"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop"/>
+    <property name="onCommentFormat" value="Checkstyle: resume"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="// START GENERATED RAW ASSEMBLER METHODS"/>
+    <property name="onCommentFormat" value="// END GENERATED RAW ASSEMBLER METHODS"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks for generated raw assembler methods"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="// START GENERATED LABEL ASSEMBLER METHODS"/>
+    <property name="onCommentFormat" value="// END GENERATED LABEL ASSEMBLER METHODS"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks for generated label assembler methods"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
+    <property name="checkFormat" value="InnerAssignment"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
+    <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
+    <property name="checkFormat" value="MemberName"/>
+    <property name="checkC" value="false"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
+  </module>
+</module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.classpath	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asm"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.base"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asmdis"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.cri"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.graal.compiler"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.graal.graph"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.project	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.oracle.max.graal.examples</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>net.sourceforge.metrics.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>net.sourceforge.metrics.nature</nature>
+		<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
+	</natures>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.settings/org.eclipse.jdt.core.prefs	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,384 @@
+#Sat Jan 22 17:02:08 CET 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=ignore
+org.eclipse.jdt.core.compiler.problem.deadCode=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=error
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=enabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=error
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=ignore
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=error
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=error
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=error
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,NORMAL
+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=48
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=4
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=8
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=true
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=200
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=false
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=error
+org.eclipse.jdt.core.incompleteClasspath=error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/.settings/org.eclipse.jdt.ui.prefs	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,75 @@
+#Fri Jul 23 17:15:05 PDT 2010
+comment_clear_blank_lines=false
+comment_format_comments=true
+comment_format_header=true
+comment_format_html=true
+comment_format_source_code=true
+comment_indent_parameter_description=true
+comment_indent_root_tags=true
+comment_line_length=120
+comment_new_line_for_parameter=true
+comment_separate_root_tags=true
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_MaxineJavaCodeStyle2
+formatter_settings_version=11
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.javadoc=false
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=0
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=0
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return Returns the ${bare_field_name}.\n */</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n *\n * @author ${user}\n */</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*\n * Copyright (c) 2007 Sun Microsystems, Inc.  All rights reserved.\n *\n * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product\n * that is described in this document. In particular, and without limitation, these intellectual property\n * rights may include one or more of the U.S. patents listed at http\://www.sun.com/patents and one or\n * more additional patents or pending patent applications in the U.S. and in other countries.\n *\n * U.S. Government Rights - Commercial software. Government users are subject to the Sun\n * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its\n * supplements.\n *\n * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or\n * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks\n * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the\n * U.S. and other countries.\n *\n * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open\n * Company, Ltd.\n */\n</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} The ${bare_field_name} to set.\n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.InliningGuide	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.inlining.InliningGuideImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.intrinsics.IntrinsifierImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.Optimizer	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.opt.OptimizerImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.FrameModifier	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.deopt.FrameModifierImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.InliningGuide	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.inlining.InliningGuideImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.intrinsics.IntrinsifierImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.Optimizer	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.opt.OptimizerImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/Main.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples;
+
+import com.oracle.max.graal.examples.deopt.*;
+import com.oracle.max.graal.examples.inlining.*;
+import com.oracle.max.graal.examples.intrinsics.*;
+import com.oracle.max.graal.examples.opt.*;
+
+
+public class Main {
+
+    public static void main(String[] args) {
+//        InliningExample.run();
+//        SafeAddExample.run();
+//        OptimizationExample.run();
+        DeoptExample.run();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/DeoptExample.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.deopt;
+
+import com.oracle.max.graal.examples.intrinsics.*;
+
+
+public class DeoptExample {
+
+    public static void run() {
+        System.out.println();
+        System.out.println();
+        System.out.println("Running Deopt Example");
+        long start = System.currentTimeMillis();
+        System.out.println("result1=" + test());
+        System.out.println("time=" + (System.currentTimeMillis() - start) + "ms");
+    }
+
+    private static int test() {
+        try {
+            return testDeopt(3000000);
+        } catch (IllegalStateException e) {
+            System.out.println(e.getMessage());
+            return 0;
+        }
+    }
+
+    private static int testDeopt(int n) {
+        int sum = 0;
+        for (int i = 0; i < n; i = SafeAddExample.safeAdd(i, 1)) {
+            sum = SafeAddExample.safeAdd(sum, i);
+        }
+        return sum;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/DeoptHandler.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.deopt;
+
+
+public class DeoptHandler {
+
+
+    public static int test(int bci, Object[] values) {
+        System.out.println("values at bci " + bci + ": ");
+        for (Object value : values) {
+            System.out.print(value + " ");
+        }
+        System.out.println();
+        return 2;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/FrameModifierImpl.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.deopt;
+
+import com.oracle.max.graal.extensions.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class FrameModifierImpl implements FrameModifier {
+
+    @Override
+    public CiFrame getFrame(RiRuntime runtime, CiFrame frame) {
+        try {
+            DeoptHandler.class.getMethod("test", Integer.TYPE, Object[].class);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return frame;
+        }
+        if (frame.method.name().equals("testDeopt")) {
+            RiType type = runtime.getType(DeoptHandler.class);
+            RiMethod method = type.getMethod("test", "(I[Ljava/lang/Object;)I");
+            System.out.println("Size: " + method.maxLocals() + " " + method.maxStackSize());
+            RiType arrayType = runtime.getType(Object.class).arrayOf();
+            CiValue[] values = new CiValue[frame.values.length];
+            for (int i = 0; i < values.length; i++) {
+                values[i] = CiVirtualObject.proxy(runtime, frame.values[i], i + 2);
+            }
+            CiVirtualObject local = CiVirtualObject.get(arrayType, values, 0);
+            CiValue[] values2 = new CiValue[method.maxLocals()];
+            values2[0] = CiConstant.forInt(frame.bci);
+            values2[1] = local;
+            for (int i = 2; i < values2.length; i++) {
+                values2[i] = CiValue.IllegalValue;
+            }
+            return new CiFrame((CiFrame) frame.caller, method, 0, false, values2, method.maxLocals(), 0, 0);
+        }
+        return frame;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/inlining/InliningExample.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.inlining;
+
+
+public class InliningExample {
+
+    public static void run() {
+        System.out.println();
+        System.out.println();
+        System.out.println("Running Inlining Example");
+        long start = System.currentTimeMillis();
+        System.out.println("result1=" + test());
+        System.out.println("result2=" + testFib());
+        System.out.println("time=" + (System.currentTimeMillis() - start) + "ms");
+    }
+
+    private static int test() {
+        return alwaysInline(30);
+    }
+
+    public static int testFib() {
+        int sum = 0;
+        for (int i = 0; i < 100000000; ++i) {
+            sum += fib(5);
+        }
+        return sum;
+    }
+
+    public static int alwaysInline(int value) {
+        if (value == 0) {
+            return neverInline(value);
+        }
+        return alwaysInline(value - 1);
+    }
+
+    public static int neverInline(int value) {
+        if (value == 0) {
+            return 0;
+        }
+        return neverInline(value - 1);
+    }
+
+    public static int fib(int val) {
+        if (val == 0 || val == 1) {
+            return 1;
+        }
+        return fib(val - 1) + fib(val - 2);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/inlining/InliningGuideImpl.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.inlining;
+
+import com.oracle.max.graal.extensions.*;
+import com.sun.cri.ri.*;
+
+
+public class InliningGuideImpl implements InliningGuide {
+
+    @Override
+    public InliningHint getHint(int depth, RiMethod caller, int bci, RiMethod target) {
+        if (target.name().equals("neverInline")) {
+            return InliningHint.NEVER_INLINE;
+        } else if (target.name().equals("alwaysInline") && depth < 50) {
+            return InliningHint.ALWAYS_INLINE;
+        } else if (target.name().equals("fib") && depth < 5) {
+            return InliningHint.ALWAYS_INLINE;
+        }
+        return InliningHint.NONE;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/IntrinsifierImpl.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.intrinsics;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.extensions.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class IntrinsifierImpl implements Intrinsifier {
+
+    @Override
+    public Graph intrinsicGraph(RiRuntime runtime, RiMethod caller, int bci, RiMethod method, List<? extends Node> parameters) {
+        if (method.holder().name().equals("Lcom/oracle/max/graal/examples/intrinsics/SafeAddExample;") && method.name().equals("safeAdd")) {
+            CompilerGraph graph = new CompilerGraph(runtime);
+            Return returnNode = new Return(new SafeAdd(new Local(CiKind.Long, 0, graph), new Local(CiKind.Long, 1, graph), graph), graph);
+            graph.start().setNext(returnNode);
+            graph.setReturn(returnNode);
+            return graph;
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAdd.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.intrinsics;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class SafeAdd extends IntegerArithmetic {
+    public SafeAdd(Value x, Value y, Graph graph) {
+        super(CiKind.Int, Bytecodes.LADD, x, y, graph);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new SafeAdd(null, null, into);
+    }
+
+    @Override
+    public String shortName() {
+        return "[+]";
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) GENERATOR_OP;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static final LIRGenerator.LIRGeneratorOp GENERATOR_OP = new LIRGenerator.LIRGeneratorOp() {
+        @Override
+        public void generate(Node n, LIRGenerator generator) {
+            SafeAdd add = (SafeAdd) n;
+            generator.arithmeticOpInt(Bytecodes.IADD, generator.createResultVariable(add), generator.load(add.x()), generator.load(add.y()), CiValue.IllegalValue);
+            generator.deoptimizeOn(Condition.OF);
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAddExample.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.intrinsics;
+
+
+public class SafeAddExample {
+
+    public static final int N = 100000000;
+
+    public static void run() {
+        System.out.println();
+        System.out.println();
+        System.out.println("Running SafeAdd Example");
+        long start = System.currentTimeMillis();
+        System.out.println("result=" + testSafeAdd());
+        System.out.println("time=" + (System.currentTimeMillis() - start) + "ms");
+    }
+
+    private static int testSafeAdd() {
+        int sum = 0;
+        int j = N;
+        for (int i = -N; i < N; ++i) {
+            sum = safeAdd(sum, i);
+            sum = safeAdd(sum, j);
+            --j;
+        }
+        return sum;
+    }
+
+    public static int safeAdd(int a, int b) {
+        int result = a + b;
+        if (b < 0 && result > a) {
+            throw new IllegalStateException("underflow when adding " + a + " and " + b);
+        } else if (b > 0 && result < a) {
+            throw new IllegalStateException("overflow when adding " + a + " and " + b);
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizationExample.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.opt;
+
+import com.oracle.max.graal.examples.intrinsics.*;
+
+
+public class OptimizationExample {
+
+    public static void run() {
+        System.out.println();
+        System.out.println();
+        System.out.println("Running Optimization Example");
+        long start = System.currentTimeMillis();
+        System.out.println("result=" + test(1000000000));
+        System.out.println("time=" + (System.currentTimeMillis() - start) + "ms");
+    }
+
+    private static long test(int n) {
+        long sum = 0;
+        for (int i = 0; i < n; i = SafeAddExample.safeAdd(i, 1)) {
+            sum = sum + i;
+        }
+        return sum;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizerImpl.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.opt;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.examples.intrinsics.*;
+import com.oracle.max.graal.extensions.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class OptimizerImpl implements Optimizer {
+
+    @Override
+    public void optimize(RiRuntime runtime, Graph graph) {
+        for (SafeAdd safeAdd : graph.getNodes(SafeAdd.class)) {
+            if (safeAdd.y().isConstant() && safeAdd.y().asConstant().asLong() == 1) {
+                if (safeAdd.x() instanceof Phi) {
+                    Phi phi = (Phi) safeAdd.x();
+                    if (phi.merge() instanceof LoopBegin && phi.valueAt(1) == safeAdd) {
+                        LoopBegin loopBegin = (LoopBegin) phi.merge();
+                        if (!canOverflow(phi, loopBegin)) {
+                            IntegerAdd add = new IntegerAdd(CiKind.Int, safeAdd.x(), safeAdd.y(), graph);
+                            safeAdd.replaceAndDelete(add);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean canOverflow(Phi phi, LoopBegin loopBegin) {
+
+        NodeBitMap nodes = LoopUtil.computeLoopNodes(loopBegin);
+        NodeBitMap exits = LoopUtil.computeLoopExits(loopBegin, nodes);
+        for (Node exit : exits) {
+            TTY.println("exit: " + exit);
+            Node pred = exit.predecessors().get(0);
+            if (pred instanceof If) {
+                If ifNode = (If) pred;
+                if (ifNode.compare() instanceof Compare) {
+                    Compare compare = (Compare) ifNode.compare();
+                    Condition cond = compare.condition();
+                    Value x = compare.x();
+                    Value y = compare.y();
+                    if (ifNode.trueSuccessor() == pred) {
+                        cond = cond.negate();
+                    }
+                    if (cond == Condition.LT && x == phi) {
+                        return false;
+                    }
+                    if (cond == Condition.GT && y == phi) {
+                        return false;
+                    }
+                }
+
+            }
+        }
+        TTY.println("can overflow");
+        return true;
+    }
+}
--- a/graal/com.oracle.max.graal.runtime/README.txt	Fri Jul 08 14:49:01 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-The classes from the projects C1X, CRI, and HotSpotVM have to be on the classpath. The classes of the HotSpotVM project have to be on the bootclasspath
-Example command line arguments for HotSpot:
--XX:+UseC1X -XX:TraceC1X=5 -Xbootclasspath/a:THIS_DIRECTORY/bin;MAXINE_DIR/C1X/bin;MAXINE_DIR/CRI/bin SomeClass
-
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Fri Jul 08 15:00:16 2011 +0200
@@ -27,16 +27,18 @@
 import java.util.*;
 
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.runtime.nodes.*;
+import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ci.CiTargetMethod.Call;
 import com.sun.cri.ci.CiTargetMethod.DataPatch;
 import com.sun.cri.ci.CiTargetMethod.Safepoint;
 import com.sun.cri.ri.*;
+import com.sun.cri.ri.RiType.Representation;
 import com.sun.max.asm.dis.*;
 import com.sun.max.lang.*;
 
@@ -247,6 +249,10 @@
 
     @Override
     public void lower(Node n, CiLoweringTool tool) {
+        if (!GraalOptions.Lower) {
+            return;
+        }
+
         if (n instanceof LoadField) {
             LoadField field = (LoadField) n;
             if (field.isVolatile()) {
@@ -278,11 +284,78 @@
                 memoryWrite.setNext(field.next());
             }
             field.replaceAndDelete(memoryWrite);
+        } else if (n instanceof LoadIndexed) {
+            LoadIndexed loadIndexed = (LoadIndexed) n;
+            Graph graph = loadIndexed.graph();
+            GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool);
+
+            CiKind elementKind = loadIndexed.elementKind();
+            LocationNode arrayLocation = createArrayLocation(graph, elementKind);
+            arrayLocation.setIndex(loadIndexed.index());
+            ReadNode memoryRead = new ReadNode(elementKind.stackKind(), loadIndexed.array(), arrayLocation, graph);
+            memoryRead.setGuard(boundsCheck);
+            memoryRead.setNext(loadIndexed.next());
+            loadIndexed.replaceAndDelete(memoryRead);
+        } else if (n instanceof StoreIndexed) {
+            StoreIndexed storeIndexed = (StoreIndexed) n;
+            Graph graph = storeIndexed.graph();
+            Anchor anchor = new Anchor(graph);
+            GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool);
+            anchor.addGuard(boundsCheck);
+
+
+            CiKind elementKind = storeIndexed.elementKind();
+            LocationNode arrayLocation = createArrayLocation(graph, elementKind);
+            arrayLocation.setIndex(storeIndexed.index());
+            Value value = storeIndexed.value();
+            Value array = storeIndexed.array();
+            if (elementKind == CiKind.Object && !value.isNullConstant()) {
+                // Store check!
+                if (array.exactType() != null) {
+                    RiType elementType = array.exactType().componentType();
+                    if (elementType.superType() != null) {
+                        Constant type = new Constant(elementType.getEncoding(Representation.ObjectHub), graph);
+                        value = new CheckCast(type, value, graph);
+                    } else {
+                        assert elementType.name().equals("Ljava/lang/Object;") : elementType.name();
+                    }
+                } else {
+                    ReadNode arrayElementKlass = readArrayElementKlass(graph, array);
+                    value = new CheckCast(arrayElementKlass, value, graph);
+                }
+            }
+            WriteNode memoryWrite = new WriteNode(elementKind.stackKind(), array, value, arrayLocation, graph);
+            memoryWrite.setGuard(boundsCheck);
+            memoryWrite.setStateAfter(storeIndexed.stateAfter());
+            anchor.setNext(memoryWrite);
+            if (elementKind == CiKind.Object && !value.isNullConstant()) {
+                ArrayWriteBarrier writeBarrier = new ArrayWriteBarrier(array, arrayLocation, graph);
+                memoryWrite.setNext(writeBarrier);
+                writeBarrier.setNext(storeIndexed.next());
+            } else {
+                memoryWrite.setNext(storeIndexed.next());
+            }
+            storeIndexed.replaceAtPredecessors(anchor);
+            storeIndexed.delete();
         }
     }
 
+    private ReadNode readArrayElementKlass(Graph graph, Value array) {
+        ReadNode arrayKlass = readHub(graph, array);
+        ReadNode arrayElementKlass = new ReadNode(CiKind.Object, arrayKlass, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph), graph);
+        return arrayElementKlass;
+    }
+
+    private LocationNode createArrayLocation(Graph graph, CiKind elementKind) {
+        return LocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), graph);
+    }
+
+    private GuardNode createBoundsCheck(AccessIndexed n, CiLoweringTool tool) {
+        return (GuardNode) tool.createGuard(new Compare(n.index(), Condition.BT, n.length(), n.graph()));
+    }
+
     @Override
-    public Graph intrinsicGraph(RiMethod method, List<? extends Node> parameters) {
+    public Graph intrinsicGraph(RiMethod caller, int bci, RiMethod method, List<? extends Node> parameters) {
         if (!intrinsicGraphs.containsKey(method)) {
             RiType holder = method.holder();
             String fullName = method.name() + method.signature().asString();
@@ -291,7 +364,7 @@
                 if (fullName.equals("getClass()Ljava/lang/Class;")) {
                     CompilerGraph graph = new CompilerGraph(this);
                     Local receiver = new Local(CiKind.Object, 0, graph);
-                    ReadNode klassOop = new ReadNode(CiKind.Object, receiver, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), graph);
+                    ReadNode klassOop = readHub(graph, receiver);
                     Return ret = new Return(new ReadNode(CiKind.Object, klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), graph), graph);
                     graph.start().setNext(ret);
                     graph.setReturn(ret);
@@ -304,7 +377,7 @@
                     Local srcPos = new Local(CiKind.Int, 1, graph);
                     Local dest = new Local(CiKind.Object, 2, graph);
                     Local destPos = new Local(CiKind.Int, 3, graph);
-                    Local length = new Local(CiKind.Int, 4, graph);
+                    Value length = new Local(CiKind.Int, 4, graph);
                     src.setDeclaredType(((Value) parameters.get(0)).declaredType());
                     dest.setDeclaredType(((Value) parameters.get(2)).declaredType());
 
@@ -321,11 +394,13 @@
                     }
 
                     CiKind componentType = src.declaredType().componentType().kind();
-
                     if (componentType == CiKind.Object) {
                         return null;
                     }
 
+                    FrameState stateBefore = new FrameState(method, FrameState.BEFORE_BCI, 0, 0, 0, false, graph);
+                    FrameState stateAfter = new FrameState(method, FrameState.AFTER_BCI, 0, 0, 0, false, graph);
+
                     // Add preconditions.
                     FixedGuard guard = new FixedGuard(graph);
                     ArrayLength srcLength = new ArrayLength(src, graph);
@@ -345,11 +420,13 @@
                     CreateVectorNode normalVector = new CreateVectorNode(false, length, graph);
                     ReadVectorNode values = new ReadVectorNode(new IntegerAddVectorNode(normalVector, srcPos, graph), src, location, graph);
                     new WriteVectorNode(new IntegerAddVectorNode(normalVector, destPos, graph), dest, location, values, graph);
+                    normalVector.setStateAfter(stateAfter);
 
                     // Build reverse vector instruction.
                     CreateVectorNode reverseVector = new CreateVectorNode(true, length, graph);
                     ReadVectorNode reverseValues = new ReadVectorNode(new IntegerAddVectorNode(reverseVector, srcPos, graph), src, location, graph);
                     new WriteVectorNode(new IntegerAddVectorNode(reverseVector, destPos, graph), dest, location, reverseValues, graph);
+                    reverseVector.setStateAfter(stateAfter);
 
                     If ifNode = new If(new Compare(src, Condition.EQ, dest, graph), graph);
                     guard.setNext(ifNode);
@@ -362,23 +439,81 @@
                     Merge merge1 = new Merge(graph);
                     merge1.addEnd(new EndNode(graph));
                     merge1.addEnd(new EndNode(graph));
+                    merge1.setStateAfter(stateBefore);
 
-                    ifNode.setFalseSuccessor(merge1.endAt(0));
+
+                    Invoke newInvoke = null;
+                    if (componentType == CiKind.Object) {
+                        Value srcClass = readHub(graph, src);
+                        Value destClass = readHub(graph, dest);
+                        If elementClassIf = new If(new Compare(srcClass, Condition.EQ, destClass, graph), graph);
+                        ifNode.setFalseSuccessor(elementClassIf);
+                        newInvoke = new Invoke(bci, Bytecodes.INVOKESTATIC, CiKind.Void, new Value[]{src, srcPos, dest, destPos, length}, method, method.signature().returnType(method.holder()), graph);
+                        newInvoke.setCanInline(false);
+                        newInvoke.setStateAfter(stateAfter);
+                        elementClassIf.setFalseSuccessor(newInvoke);
+                        elementClassIf.setTrueSuccessor(merge1.endAt(0));
+                    } else {
+                        ifNode.setFalseSuccessor(merge1.endAt(0));
+                    }
+
                     secondIf.setFalseSuccessor(merge1.endAt(1));
                     merge1.setNext(normalVector);
 
                     Merge merge2 = new Merge(graph);
                     merge2.addEnd(new EndNode(graph));
                     merge2.addEnd(new EndNode(graph));
+                    merge2.setStateAfter(stateAfter);
 
                     normalVector.setNext(merge2.endAt(0));
                     reverseVector.setNext(merge2.endAt(1));
 
+                    if (newInvoke != null) {
+                        merge2.addEnd(new EndNode(graph));
+                        newInvoke.setNext(merge2.endAt(2));
+                    }
+
                     Return ret = new Return(null, graph);
                     merge2.setNext(ret);
                     graph.setReturn(ret);
                     return graph;
                 }
+            } else if (holderName.equals("Ljava/lang/Float;")) {
+                if (fullName.equals("floatToRawIntBits(F)I") || fullName.equals("floatToIntBits(F)I")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Int, new Local(CiKind.Float, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                } else if (fullName.equals("intBitsToFloat(I)F")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Float, new Local(CiKind.Int, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
+            } else if (holderName.equals("Ljava/lang/Double;")) {
+                if (fullName.equals("doubleToRawLongBits(D)J") || fullName.equals("doubleToLongBits(D)J")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Long, new Local(CiKind.Double, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                } else if (fullName.equals("longBitsToDouble(J)D")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Double, new Local(CiKind.Long, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
+            } else if (holderName.equals("Ljava/lang/Thread;")) {
+                if (fullName.equals("currentThread()Ljava/lang/Thread;")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new CurrentThread(config.threadObjectOffset, graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
             }
 
             if (!intrinsicGraphs.containsKey(method)) {
@@ -387,4 +522,13 @@
         }
         return intrinsicGraphs.get(method);
     }
+
+    private ReadNode readHub(Graph graph, Value value) {
+        return new ReadNode(CiKind.Object, value, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), graph);
+    }
+
+    @Override
+    public RiType getType(Class<?> clazz) {
+        return compiler.getVMEntries().getType(clazz);
+    }
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypePrimitive.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypePrimitive.java	Fri Jul 08 15:00:16 2011 +0200
@@ -154,4 +154,9 @@
     public RiField[] fields() {
         return null;
     }
+
+    @Override
+    public RiMethod getMethod(String name, String signature) {
+        return null;
+    }
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl.java	Fri Jul 08 15:00:16 2011 +0200
@@ -230,4 +230,9 @@
         }
         return fields;
     }
+
+    @Override
+    public RiMethod getMethod(String name, String signature) {
+        return compiler.getVMEntries().RiType_resolveMethodImpl(this, name, signature);
+    }
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeUnresolved.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeUnresolved.java	Fri Jul 08 15:00:16 2011 +0200
@@ -205,4 +205,9 @@
     public RiField[] fields() {
         return null;
     }
+
+    @Override
+    public RiMethod getMethod(String name, String signature) {
+        return null;
+    }
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java	Fri Jul 08 15:00:16 2011 +0200
@@ -164,8 +164,8 @@
         protected XirTemplate create(CiXirAssembler asm, long flags) {
             asm.restart(CiKind.Void);
 
-            // XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax);
-            // asm.pload(CiKind.Word, temp, asm.w(config.safepointPollingAddress), true);
+            XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax);
+            asm.pload(CiKind.Word, temp, asm.w(config.safepointPollingAddress), true);
 
             return asm.finishTemplate("safepoint");
         }
@@ -1179,7 +1179,6 @@
 
     @Override
     public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) {
-        assert type.isResolved();
         return new XirSnippet(checkCastTemplates.get(site), receiver, hub);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,99 @@
+/*
+ * 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.runtime.nodes;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class ArrayWriteBarrier extends WriteBarrier {
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_OBJECT = 0;
+    private static final int INPUT_LOCATION = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public void setObject(Value n) {
+        inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public LocationNode location() {
+        return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION);
+    }
+
+    public void setLocation(LocationNode n) {
+        inputs().set(super.inputCount() + INPUT_LOCATION, n);
+    }
+
+    public ArrayWriteBarrier(Value object, LocationNode index, Graph graph) {
+        super(INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.setObject(object);
+        this.setLocation(index);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    assert n == ArrayWriteBarrier.this;
+                    CiVariable temp = generator.newVariable(CiKind.Word);
+                    generator.lir().lea(location().createAddress(generator, object()), temp);
+                    ArrayWriteBarrier.this.generateBarrier(temp, generator);
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("field write barrier ").print(object());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new ArrayWriteBarrier(null, null, into);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/CurrentThread.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,73 @@
+/*
+ * 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.runtime.nodes;
+
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class CurrentThread extends FloatingNode {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+    private int threadObjectOffset;
+
+    public CurrentThread(int threadObjectOffset, Graph graph) {
+        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.threadObjectOffset = threadObjectOffset;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    CurrentThread conv = (CurrentThread) n;
+                    CiValue result = generator.createResultVariable(conv);
+                    generator.lir().move(new CiAddress(CiKind.Object, AMD64.r15.asValue(CiKind.Word), threadObjectOffset), result);
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof CurrentThread;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("currentThread");
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new CurrentThread(threadObjectOffset, into);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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.runtime.nodes;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class FPConversionNode extends FloatingNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public void setValue(Value n) {
+        inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    public FPConversionNode(CiKind kind, Value value, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.setValue(value);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    FPConversionNode conv = (FPConversionNode) n;
+                    CiValue reg = generator.createResultVariable(conv);
+                    CiValue value = generator.load(conv.value());
+                    CiValue tmp = generator.forceToSpill(value, conv.kind, false);
+                    generator.lir().move(tmp, reg);
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof FPConversionNode && ((FPConversionNode) i).kind == kind;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("fp conversion node ").print(value());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new FPConversionNode(kind, null, into);
+    }
+}
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java	Fri Jul 08 14:49:01 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java	Fri Jul 08 15:00:16 2011 +0200
@@ -25,13 +25,11 @@
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.ir.*;
-import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.runtime.*;
 import com.sun.cri.ci.*;
 
 
-public final class FieldWriteBarrier extends FixedNodeWithNext {
+public final class FieldWriteBarrier extends WriteBarrier {
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_OBJECT = 0;
 
@@ -54,7 +52,7 @@
     }
 
     public FieldWriteBarrier(Value object, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.setObject(object);
     }
 
@@ -68,18 +66,8 @@
                 public void generate(Node n, LIRGenerator generator) {
                     assert n == FieldWriteBarrier.this;
                     CiVariable temp = generator.newVariable(CiKind.Word);
-                    HotSpotVMConfig config = CompilerImpl.getInstance().getConfig();
                     generator.lir().move(generator.makeOperand(object()), temp);
-                    generator.lir().unsignedShiftRight(temp, CiConstant.forInt(config.cardtableShift), temp, CiValue.IllegalValue);
-
-                    long startAddress = config.cardtableStartAddress;
-                    int displacement = 0;
-                    if (((int) startAddress) == startAddress) {
-                        displacement = (int) startAddress;
-                    } else {
-                        generator.lir().add(temp, CiConstant.forLong(config.cardtableStartAddress), temp);
-                    }
-                    generator.lir().move(CiConstant.FALSE, new CiAddress(CiKind.Boolean, temp, displacement), (LIRDebugInfo) null);
+                    FieldWriteBarrier.this.generateBarrier(temp, generator);
                 }
             };
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,55 @@
+/*
+ * 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.runtime.nodes;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.runtime.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class WriteBarrier extends FixedNodeWithNext {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public WriteBarrier(int inputCount, int successorCount, Graph graph) {
+        super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+
+
+    protected void generateBarrier(CiValue temp, LIRGenerator generator) {
+        HotSpotVMConfig config = CompilerImpl.getInstance().getConfig();
+        generator.lir().unsignedShiftRight(temp, CiConstant.forInt(config.cardtableShift), temp, CiValue.IllegalValue);
+
+        long startAddress = config.cardtableStartAddress;
+        int displacement = 0;
+        if (((int) startAddress) == startAddress) {
+            displacement = (int) startAddress;
+        } else {
+            generator.lir().add(temp, CiConstant.forLong(config.cardtableStartAddress), temp);
+        }
+        generator.lir().move(CiConstant.FALSE, new CiAddress(CiKind.Boolean, temp, displacement), (LIRDebugInfo) null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/perf/benchmarktool.sh	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,156 @@
+#!/usr/bin/python
+
+import subprocess
+import os
+import re
+import sys
+import argparse
+
+DEFAULT_DACAPO_OPTS = " -XX:MaxPermSize=512m -Xms1g -Xmx2g "
+DEFAULT_SCIMARK_OPTS = " -Xms32m -Xmx100m "
+
+def runBash(cmd):
+    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    return p.stdout
+
+def s2msString(floatString):
+    return str(round(float(floatString)*1000))
+
+# Raw String Notation (r"") : \ instead of \\
+graalTime = re.compile(r"Total compilation time\s+:\s+([0-9]+\.[0-9]+) s")
+graalSubTime = re.compile(r"([a-zA-Z0-9_ ]+)\s+:\s+([0-9]+\.[0-9]+) s \([0-9 ][0-9]\.[0-9]{2}%\)")
+
+def matchGraalTime(string, csvOutput, csvOutputLine, writeHeaderAt):
+    match1 = graalTime.search(string)
+    match2 = graalSubTime.search(string)
+    if match1:
+        if csvOutputLine == writeHeaderAt:
+            csvOutput[0].append('graal total')
+        print('Graal total time: '+ s2msString(match1.group(1)))
+        csvOutput[csvOutputLine].append(s2msString(match1.group(1)))
+    elif match2:
+        if csvOutputLine == writeHeaderAt:
+            csvOutput[0].append(match2.group(1).strip())
+        print('Graal specific time: '+match2.group(1)+': '+s2msString(match2.group(2)))
+        csvOutput[csvOutputLine].append(s2msString(match2.group(2)))
+    else:
+        print('# '+string)
+
+def writeout(outputFile, csvOutput):
+    for csvLine in csvOutput :
+        outputFile.write(';'.join(csvLine)+';'+os.linesep)
+
+def main():
+    # Check for environment variables
+    if os.getenv('JDK7') is None:
+        print('Environment variable JDK7 is not defined.')
+        return 1
+    if os.getenv('DACAPO') is None:
+        print('Environment variable DACAPO is not defined. It must point to a directory with the DaCapo benchmark jar.')
+        return 1
+    if os.getenv('SCIMARK') is None:
+        print('Environment variable SCIMARK is not defined. It must point to a directory with the SciMark benchmark jar.')
+        return 1
+    if os.getenv('REFERENCE_JDK') is None:
+        print('Environment variable REFERENCE_JDK is not defined.')
+        return 1
+    
+    # Option parsing
+    parser = argparse.ArgumentParser(description='Automated DaCapo and Scimark bechmarks')
+    parser.add_argument('-a', '-all', help='run all benchmarks for all compilers', action='store_true')
+    parser.add_argument('-c', type=str, help='compiler to use', default='graal', choices=['client', 'server', 'graal'], required=False)
+    parser.add_argument('-n', type=int, help='number of DaCapo benchmarks to run', default=20)
+    parser.add_argument('-o', type=str, help='graalVM options(quoted!)', default='')
+    parser.add_argument('-runonly', type=str, help='run specified benchmark only', default='all')
+    options = parser.parse_args()
+    compilerFlags = {'graal' : '-client -graal -G:+Time -XX:-GraalBailoutIsFatal -G:QuietBailout ',
+        'client' : '-client',
+        'server' : '-server'}
+
+    if options.a: 
+        compilers = ['graal', 'client', 'server']
+    else:
+        compilers = [options.c]
+    
+    for compiler in compilers:
+    
+        outputFile = open(compiler+'.csv', 'w')
+    
+        # DaCapo Benchmarks
+        if compiler == 'graal':
+            vm = os.environ['JDK7']
+        else :
+            vm = os.environ['REFERENCE_JDK']
+        
+        cmd = vm + '/bin/java ' + compilerFlags[compiler] + ' -d64 ' + DEFAULT_DACAPO_OPTS + options.o + ' -classpath ' + \
+            os.environ['DACAPO'] + '/dacapo-9.12-bach.jar Harness -n ' + str(options.n) + ' '
+        benchmarks = runBash('java -jar ' + os.environ['DACAPO'] + '/dacapo-9.12-bach.jar -l').read().decode().split(' ')
+    
+        benchmarkTime = re.compile(r"===== DaCapo 9\.12 ([a-zA-Z0-9_]+) ((PASSED)|(completed warmup [0-9]+)) in ([0-9]+) msec =====")
+    
+        csvOutput = [['benchmark', 'type', 'time']]
+        csvOutputLine = 0
+        for benchmark in benchmarks:
+            if options.runonly != 'all' and benchmark != options.runonly:
+                continue
+            nRuns = 0
+            dcOutput = runBash(cmd + benchmark)
+            while True:
+                line = dcOutput.readline().decode()
+                if not line:
+                    break
+                line = line.strip()
+                match = benchmarkTime.search(line)
+                if match:
+                    csvOutputLine = csvOutputLine + 1
+                    nRuns = nRuns + 1
+                    csvOutput.append(list())
+                    csvOutput[csvOutputLine].append(str(nRuns))
+                    print('Benchmark type: '+match.group(1))
+                    print('Benchmark time: '+match.group(5))
+                    csvOutput[csvOutputLine].append(match.group(1))
+                    csvOutput[csvOutputLine].append(match.group(5))
+                else:
+                    matchGraalTime(line, csvOutput, csvOutputLine, options.n)
+                    
+            if nRuns < options.n:
+                csvOutputLine = csvOutputLine + (options.n - nRuns)
+                for i in range(options.n - nRuns):
+                    csvOutput.append([str(nRuns + i), benchmark, '0'])
+    
+        writeout(outputFile, csvOutput)
+    
+        if options.runonly != 'all' and options.runonly != 'scimark':
+            outputFile.close()
+            return 0
+        
+        # Scimark Benchmarks
+        writeout(outputFile, [['']])
+        cmd = vm + '/bin/java ' + compilerFlags[compiler] + ' -d64 ' + DEFAULT_SCIMARK_OPTS + options.o + \
+            ' -Xbootclasspath/a:' + os.environ['SCIMARK'] + '/scimark2lib.jar jnt.scimark2.commandline'
+    
+        benchmarkScore = re.compile(r"([a-zA-Z0-9_\(\),= ]+):\s+([0-9]+\.[0-9]+)$")
+    
+        csvOutput = [['run'],[]]
+        scOutput = runBash(cmd)
+        while True:
+            line = scOutput.readline().decode()
+            if not line:
+                break
+            line = line.strip()
+            match = benchmarkScore.search(line)
+            if match:
+                print('Scimark '+match.group(1)+' score: '+match.group(2))
+                csvOutput[0].append(match.group(1).strip())
+                csvOutput[1].append(match.group(2))
+            else:
+                matchGraalTime(line,csvOutput, 1, 1)
+    
+        writeout(outputFile, csvOutput)
+        outputFile.close()
+        
+    return 0
+
+#This idiom means the below code only runs when executed from command line
+if __name__ == '__main__':
+    sys.exit(main())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runexamples.sh	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,21 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+ant -f create_examples.xml
+COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -G:Extend -Xcomp -XX:CompileOnly=examples $* -jar examples.jar"
+echo $COMMAND
+$COMMAND
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runexamplescompare.sh	Fri Jul 08 15:00:16 2011 +0200
@@ -0,0 +1,27 @@
+#!/bin/bash
+if [ -z "${JDK7}" ]; then
+  echo "JDK7 is not defined."
+  exit 1;
+fi
+if [ -z "${MAXINE}" ]; then
+  echo "MAXINE is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${GRAAL}" ]; then
+  echo "GRAAL is not defined. It must point to a maxine repository directory."
+  exit 1;
+fi
+if [ -z "${DACAPO}" ]; then
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
+  exit 1;
+fi
+ant -f create_examples.xml
+COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -G:Extend -Xcomp -XX:CompileOnly=examples $* -jar examples.jar"
+echo $COMMAND
+$COMMAND
+COMMAND="${JDK7}/bin/java -client -d64 -Xms1g -Xmx2g -esa -Xcomp -XX:CompileOnly=examples $* -jar examples.jar"
+echo $COMMAND
+$COMMAND
+COMMAND="${JDK7}/bin/java -server -d64 -Xms1g -Xmx2g -esa -Xcomp -XX:CompileOnly=examples $* -jar examples.jar"
+echo $COMMAND
+$COMMAND
--- a/runscimark.sh	Fri Jul 08 14:49:01 2011 +0200
+++ b/runscimark.sh	Fri Jul 08 15:00:16 2011 +0200
@@ -12,16 +12,7 @@
   exit 1;
 fi
 if [ -z "${SCIMARK}" ]; then
-  echo "SCIMARK is not defined. It must point to a SciMark benchmark jar."
+  echo "SCIMARK is not defined. It must point to a directory with the SciMark benchmark jar."
   exit 1;
 fi
-COUNT=$1
-shift
-if [ -z "${COUNT}" ]; then
-  COUNT=5000
-fi
-for (( i = 1; i <= ${COUNT}; i++ ))      ### Outer for loop ###
-do
-  echo "$i "
-  ${JDK7}/jre/bin/java -client -d64 -graal -esa -ea -Xms32m -Xmx100m -Xbootclasspath/a:${SCIMARK} -G:+Time $@ jnt.scimark2.commandline
-done
+${JDK7}/jre/bin/java -client -d64 -graal -Xms256m -Xmx512m -Xbootclasspath/a:${SCIMARK}/scimark2lib.jar $@ jnt.scimark2.commandline
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Jul 08 14:49:01 2011 +0200
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Jul 08 15:00:16 2011 +0200
@@ -459,6 +459,7 @@
   } while (should_repeat == true);
 
   if (h_method->method_data() != NULL) {
+    ResourceMark rm(thread);
     ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci);
     if (pdata != NULL) {
       int tstate0 = pdata->trap_state();
--- a/src/share/vm/runtime/deoptimization.cpp	Fri Jul 08 14:49:01 2011 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Fri Jul 08 15:00:16 2011 +0200
@@ -1244,9 +1244,10 @@
 
     if (trap_scope->rethrow_exception()) {
       if (TraceDeoptimization) {
-        tty->print_cr("Exception to be rethrown in the interpreter");
+        tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", instanceKlass::cast(trap_method->method_holder())->name()->as_C_string(), trap_method->name()->as_C_string(), trap_bci);
       }
       GrowableArray<ScopeValue*>* expressions = trap_scope->expressions();
+      guarantee(expressions != NULL, "must have exception to throw");
       ScopeValue* topOfStack = expressions->top();
       Handle topOfStackObj = cvf->create_stack_value(topOfStack)->get_obj();
       THREAD->set_pending_exception(topOfStackObj(), NULL, 0);
--- a/src/share/vm/runtime/vframeArray.cpp	Fri Jul 08 14:49:01 2011 +0200
+++ b/src/share/vm/runtime/vframeArray.cpp	Fri Jul 08 15:00:16 2011 +0200
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "code/scopeDesc.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
@@ -62,7 +63,7 @@
   _method = vf->method();
   _bci    = vf->raw_bci();
   _reexecute = vf->should_reexecute();
-
+  
   int index;
 
   // Get the monitors off-stack
@@ -126,28 +127,37 @@
 
   // Now the expressions off-stack
   // Same silliness as above
-
-  StackValueCollection *exprs = vf->expressions();
-  _expressions = new StackValueCollection(exprs->size());
-  for(index = 0; index < exprs->size(); index++) {
-    StackValue* value = exprs->at(index);
-    switch(value->type()) {
-      case T_OBJECT:
-        assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
-        // preserve object type
-        _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT ));
-        break;
-      case T_CONFLICT:
-        // A dead stack element.  Will be initialized to null/zero.
-        // This can occur when the compiler emits a state in which stack
-        // elements are known to be dead (because of an imminent exception).
-        _expressions->add( new StackValue());
-        break;
-      case T_INT:
-        _expressions->add( new StackValue(value->get_int()));
-        break;
-      default:
-        ShouldNotReachHere();
+  bool rethrow_exception = vf->scope()->rethrow_exception();
+  if (rethrow_exception) {
+    // (tw) Make sure there are only null pointers on the stack, because the stack values do not correspond to the GC map at the bytecode at which the exception is rethrown.
+    _expressions = new StackValueCollection(vf->method()->max_stack());
+    assert(Thread::current()->has_pending_exception(), "just checking");
+    for (int i=0; i<vf->method()->max_stack(); ++i) {
+      _expressions->add( new StackValue());
+    }
+  } else {
+    StackValueCollection *exprs = vf->expressions();
+    _expressions = new StackValueCollection(exprs->size());
+    for(index = 0; index < exprs->size(); index++) {
+      StackValue* value = exprs->at(index);
+      switch(value->type()) {
+        case T_OBJECT:
+          assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
+          // preserve object type
+          _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT ));
+          break;
+        case T_CONFLICT:
+          // A dead stack element.  Will be initialized to null/zero.
+          // This can occur when the compiler emits a state in which stack
+          // elements are known to be dead (because of an imminent exception).
+          _expressions->add( new StackValue());
+          break;
+        case T_INT:
+          _expressions->add( new StackValue(value->get_int()));
+          break;
+        default:
+          ShouldNotReachHere();
+      }
     }
   }
 }
@@ -314,8 +324,7 @@
   // only unpacks the part of the expression stack not used by callee
   // as parameters. The callee parameters are unpacked as part of the
   // callee locals.
-  int i;
-  for(i = 0; i < expressions()->size(); i++) {
+  for(int i = 0; i < expressions()->size(); i++) {
     StackValue *value = expressions()->at(i);
     intptr_t*   addr  = iframe()->interpreter_frame_expression_stack_at(i);
     switch(value->type()) {
@@ -352,7 +361,7 @@
 
 
   // Unpack the locals
-  for(i = 0; i < locals()->size(); i++) {
+  for(int i = 0; i < locals()->size(); i++) {
     StackValue *value = locals()->at(i);
     intptr_t* addr  = iframe()->interpreter_frame_local_at(i);
     switch(value->type()) {