changeset 3090:536528f48708

more escape analysis work: debug info
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 28 Jun 2011 19:14:28 +0200
parents 05b8a7787aaf
children bee93b329be2
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.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/NewArray.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObject.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypePrimitive.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeUnresolved.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalCodeInstaller.hpp src/share/vm/graal/graalCompiler.cpp src/share/vm/graal/graalJavaAccess.hpp src/share/vm/graal/graalVMEntries.cpp src/share/vm/runtime/deoptimization.cpp src/share/vm/runtime/deoptimization.hpp
diffstat 26 files changed, 304 insertions(+), 157 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Tue Jun 28 19:14:28 2011 +0200
@@ -55,6 +55,7 @@
     public static int     MaximumShortLoopSize               = 5;
 
     // escape analysis settings
+    public static boolean EscapeAnalysis                     = ____;
     public static int     ForcedInlineEscapeWeight           = 0;
     public static int     MaximumEscapeAnalysisArrayLength   = 32;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Tue Jun 28 19:14:28 2011 +0200
@@ -36,6 +36,7 @@
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.*;
 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.*;
@@ -318,7 +319,7 @@
     LIRInstruction instructionForId(int opId) {
         assert isEven(opId) : "opId not even";
         LIRInstruction instr = opIdToInstructionMap[opIdToIndex(opId)];
-        assert instr.id == opId;
+        assert instr.id() == opId;
         return instr;
     }
 
@@ -460,7 +461,7 @@
             // iterate all instructions of the block. skip the first because it is always a label
             for (int j = 1; j < numInst; j++) {
                 LIRInstruction op = instructions.get(j);
-                int opId = op.id;
+                int opId = op.id();
 
                 if (opId == -1) {
                     CiValue resultOperand = op.result();
@@ -568,7 +569,7 @@
             int numInst = instructions.size();
             for (int j = 0; j < numInst; j++) {
                 LIRInstruction op = instructions.get(j);
-                op.id = opId;
+                op.setId(opId);
 
                 opIdToInstructionMap[index] = op;
                 opIdToBlockMap[index] = block;
@@ -616,7 +617,7 @@
                         if (!liveKill.get(operandNum)) {
                             liveGen.set(operandNum);
                             if (GraalOptions.TraceLinearScanLevel >= 4) {
-                                TTY.println("  Setting liveGen for operand %d at instruction %d", operandNum, op.id);
+                                TTY.println("  Setting liveGen for operand %d at instruction %d", operandNum, op.id());
                             }
                         }
                         if (block.loopIndex() >= 0) {
@@ -641,7 +642,7 @@
                                 if (!liveKill.get(operandNum)) {
                                     liveGen.set(operandNum);
                                     if (GraalOptions.TraceLinearScanLevel >= 4) {
-                                        TTY.println("  Setting liveGen for value %s, LIR opId %d, operand %d because of state for " + op.toString(), Util.valueString(value), op.id, operandNum);
+                                        TTY.println("  Setting liveGen for value %s, LIR opId %d, operand %d because of state for " + op.toString(), Util.valueString(value), op.id(), operandNum);
                                     }
                                 }
                             } else if (operand.isRegister()) {
@@ -848,13 +849,13 @@
                     if (block.liveGen.get(operandNum)) {
                         TTY.println("  used in block B%d", block.blockID());
                         for (LIRInstruction ins : block.lir().instructionsList()) {
-                            TTY.println(ins.id + ": " + ins.result() + " " + ins.toString());
+                            TTY.println(ins.id() + ": " + ins.result() + " " + ins.toString());
                         }
                     }
                     if (block.liveKill.get(operandNum)) {
                         TTY.println("  defined in block B%d", block.blockID());
                         for (LIRInstruction ins : block.lir().instructionsList()) {
-                            TTY.println(ins.id + ": " + ins.result() + " " + ins.toString());
+                            TTY.println(ins.id() + ": " + ins.result() + " " + ins.toString());
                         }
                     }
                 }
@@ -1102,8 +1103,8 @@
                 if (GraalOptions.DetailedAsserts) {
                     int argSlots = compilation.method.signature().argumentSlots(!isStatic(compilation.method.accessFlags()));
                     assert slot.index() >= 0 && slot.index() < argSlots;
-                    assert move.id > 0 : "invalid id";
-                    assert blockForId(move.id).numberOfPreds() == 0 : "move from stack must be in first block";
+                    assert move.id() > 0 : "invalid id";
+                    assert blockForId(move.id()).numberOfPreds() == 0 : "move from stack must be in first block";
                     assert move.result().isVariable() : "result of move must be a variable";
 
                     if (GraalOptions.TraceLinearScanLevel >= 4) {
@@ -1137,7 +1138,7 @@
                     if (from != null && to != null) {
                         to.setLocationHint(from);
                         if (GraalOptions.TraceLinearScanLevel >= 4) {
-                            TTY.println("operation at opId %d: added hint from interval %d to %d", move.id, from.operandNumber, to.operandNumber);
+                            TTY.println("operation at opId %d: added hint from interval %d to %d", move.id(), from.operandNumber, to.operandNumber);
                         }
                     }
                 }
@@ -1155,7 +1156,7 @@
                     if (from != null && to != null) {
                         to.setLocationHint(from);
                         if (GraalOptions.TraceLinearScanLevel >= 4) {
-                            TTY.println("operation at opId %d: added hint from interval %d to %d", cmove.id, from.operandNumber, to.operandNumber);
+                            TTY.println("operation at opId %d: added hint from interval %d to %d", cmove.id(), from.operandNumber, to.operandNumber);
                         }
                     }
                 }
@@ -1179,8 +1180,8 @@
             final int blockFrom = block.firstLirInstructionId();
             int blockTo = block.lastLirInstructionId();
 
-            assert blockFrom == instructions.get(0).id;
-            assert blockTo == instructions.get(instructions.size() - 1).id;
+            assert blockFrom == instructions.get(0).id();
+            assert blockTo == instructions.get(instructions.size() - 1).id();
 
             // Update intervals for operands live at the end of this block;
             BitMap live = block.liveOut;
@@ -1208,7 +1209,7 @@
             assert !instructions.get(0).hasOperands() : "first operation must always be a label";
             for (int j = instructions.size() - 1; j >= 1; j--) {
                 LIRInstruction op = instructions.get(j);
-                final int opId = op.id;
+                final int opId = op.id();
 
                 // add a temp range for each register if operation destroys caller-save registers
                 if (op.hasCall) {
@@ -1269,9 +1270,17 @@
                 if (info != null) {
                     info.state.forEachLiveStateValue(new ValueProcedure() {
                         public void doValue(Value value) {
-                            CiValue operand = value.operand();
-                            if (operand.isVariableOrRegister()) {
-                                addUse(operand, blockFrom, (opId + 1), RegisterPriority.None, null);
+                            if (value instanceof VirtualObject) {
+                                VirtualObject obj = (VirtualObject) value;
+                                do {
+                                    doValue(obj.input());
+                                    obj = obj.object();
+                                } while (obj != null);
+                            } else {
+                                CiValue operand = value.operand();
+                                if (operand.isVariableOrRegister()) {
+                                    addUse(operand, blockFrom, (opId + 1), RegisterPriority.None, null);
+                                }
                             }
                         }
                     });
@@ -1315,7 +1324,7 @@
                 if (GraalOptions.TraceLinearScanLevel >= 2) {
                     TTY.println("killing XMMs for trig");
                 }
-                int opId = op.id;
+                int opId = op.id();
 
                 for (CiRegister r : compilation.registerConfig.getCallerSaveRegisters()) {
                     if (r.isFpu()) {
@@ -1770,19 +1779,19 @@
 
     void computeOopMap(IntervalWalker iw, LIRInstruction op, LIRDebugInfo info, boolean isCallSite, BitMap frameRefMap, BitMap regRefMap) {
         if (GraalOptions.TraceLinearScanLevel >= 3) {
-            TTY.println("creating oop map at opId %d", op.id);
+            TTY.println("creating oop map at opId %d", op.id());
         }
 
         // walk before the current operation . intervals that start at
         // the operation (i.e. output operands of the operation) are not
         // included in the oop map
-        iw.walkBefore(op.id);
+        iw.walkBefore(op.id());
 
         // Iterate through active intervals
         for (Interval interval = iw.activeLists.get(RegisterBinding.Fixed); interval != Interval.EndMarker; interval = interval.next) {
             CiValue operand = interval.operand;
 
-            assert interval.currentFrom() <= op.id && op.id <= interval.currentTo() : "interval should not be active otherwise";
+            assert interval.currentFrom() <= op.id() && op.id() <= interval.currentTo() : "interval should not be active otherwise";
             assert interval.operand.isVariable() : "fixed interval found";
 
             // Check if this range covers the instruction. Intervals that
@@ -1791,7 +1800,7 @@
             // moves, any intervals which end at this instruction are included
             // in the oop map since we may safepoint while doing the patch
             // before we've consumed the inputs.
-            if (op.id < interval.currentTo()) {
+            if (op.id() < interval.currentTo()) {
                 // caller-save registers must not be included into oop-maps at calls
                 assert !isCallSite || !operand.isRegister() || !isCallerSave(operand) : "interval is in a caller-save register at a call . register will be overwritten";
 
@@ -1803,7 +1812,7 @@
 
                 // Spill optimization: when the stack value is guaranteed to be always correct,
                 // then it must be added to the oop map even if the interval is currently in a register
-                if (interval.alwaysInMemory() && op.id > interval.spillDefinitionPos() && !interval.location().equals(interval.spillSlot())) {
+                if (interval.alwaysInMemory() && op.id() > interval.spillDefinitionPos() && !interval.location().equals(interval.spillSlot())) {
                     assert interval.spillDefinitionPos() > 0 : "position not set correctly";
                     assert interval.spillSlot() != null : "no spill slot assigned";
                     assert !interval.operand.isRegister() : "interval is on stack :  so stack slot is registered twice";
@@ -1837,7 +1846,9 @@
     }
 
     CiValue toCiValue(int opId, Value value) {
-        if (value != null && value.operand() != CiValue.IllegalValue) {
+        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) {
@@ -1884,6 +1895,33 @@
         }
     }
 
+    private CiVirtualObject toCiVirtualObject(int opId, VirtualObject obj) {
+        RiType type = obj.type();
+        EscapeField[] escapeFields = obj.fields();
+        CiValue[] values = new CiValue[escapeFields.length];
+
+        VirtualObject current = obj;
+        do {
+            boolean found = false;
+            for (int i = 0; i < escapeFields.length; i++) {
+                if (escapeFields[i] == current.field() && values[i] == null) {
+                    values[i] = toCiValue(opId, current.input());
+                    found = true;
+                    break;
+                }
+            }
+            assert found;
+            current = current.object();
+        } while (current != null);
+
+        for (CiValue val : values) {
+            assert val != null;
+        }
+
+        CiVirtualObject vobj = CiVirtualObject.get(type, values, obj.id());
+        return vobj;
+    }
+
     CiFrame computeFrameForState(FrameState state, int opId, BitMap frameRefMap) {
         CiValue[] values = new CiValue[state.valuesSize() + state.locksSize()];
         int valueIndex = 0;
@@ -1937,11 +1975,11 @@
                 int frameWords = frameSize / compilation.target.spillSlotSize;
                 BitMap frameRefMap = new BitMap(frameWords);
                 BitMap regRefMap = !op.hasCall ? new BitMap(compilation.target.arch.registerReferenceMapBitCount) : null;
-                CiFrame frame = compilation.placeholderState != null ? null : computeFrame(info.state, op.id, frameRefMap);
+                CiFrame frame = compilation.placeholderState != null ? null : computeFrame(info.state, op.id(), frameRefMap);
                 computeOopMap(iw, op, info, frameRefMap, regRefMap);
                 info.debugInfo = new CiDebugInfo(frame, regRefMap, frameRefMap);
             } else if (GraalOptions.DetailedAsserts) {
-                assert info.debugInfo.frame().equals(computeFrame(info.state, op.id, new BitMap(info.debugInfo.frameRefMap.size())));
+                assert info.debugInfo.frame().equals(computeFrame(info.state, op.id(), new BitMap(info.debugInfo.frameRefMap.size())));
             }
         }
     }
@@ -1970,7 +2008,7 @@
                 for (int k = 0; k < n; k++) {
                     CiValue operand = op.operandAt(mode, k);
                     if (operand.isVariable()) {
-                        op.setOperandAt(mode, k, colorLirOperand((CiVariable) operand, op.id, mode));
+                        op.setOperandAt(mode, k, colorLirOperand((CiVariable) operand, op.id(), mode));
                     }
                 }
             }
@@ -2256,14 +2294,14 @@
                 LIRInstruction op = instructions.get(j);
 
                 if (op.info != null) {
-                    iw.walkBefore(op.id);
+                    iw.walkBefore(op.id());
                     boolean checkLive = true;
 
                     // Make sure none of the fixed registers is live across an
                     // oopmap since we can't handle that correctly.
                     if (checkLive) {
                         for (Interval interval = iw.activeLists.get(RegisterBinding.Fixed); interval != Interval.EndMarker; interval = interval.next) {
-                            if (interval.currentTo() > op.id + 1) {
+                            if (interval.currentTo() > op.id() + 1) {
                                 // This interval is live out of this op so make sure
                                 // that this interval represents some value that's
                                 // referenced by this op either as an input or output.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java	Tue Jun 28 19:14:28 2011 +0200
@@ -233,15 +233,15 @@
         // When the block already contains spill moves, the index must be increased until the
         // correct index is reached.
         List<LIRInstruction> list = opBlock.lir().instructionsList();
-        int index = (opId - list.get(0).id) >> 1;
-        assert list.get(index).id <= opId : "error in calculation";
+        int index = (opId - list.get(0).id()) >> 1;
+        assert list.get(index).id() <= opId : "error in calculation";
 
-        while (list.get(index).id != opId) {
+        while (list.get(index).id() != opId) {
             index++;
             assert 0 <= index && index < list.size() : "index out of bounds";
         }
         assert 1 <= index && index < list.size() : "index out of bounds";
-        assert list.get(index).id == opId : "error in calculation";
+        assert list.get(index).id() == opId : "error in calculation";
 
         // insert new instruction before instruction at position index
         moveResolver.moveInsertPosition(opBlock.lir(), index - 1);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java	Tue Jun 28 19:14:28 2011 +0200
@@ -229,8 +229,8 @@
                 CiValue operand = op.operandAt(LIRInstruction.OperandMode.Input, j);
                 if (allocator.isProcessed(operand)) {
                     Interval interval = intervalAt(operand);
-                    if (op.id != -1) {
-                        interval = interval.getSplitChildAtOpId(op.id, LIRInstruction.OperandMode.Input, allocator);
+                    if (op.id() != -1) {
+                        interval = interval.getSplitChildAtOpId(op.id(), LIRInstruction.OperandMode.Input, allocator);
                     }
 
                     assert checkState(inputState, interval.location(), interval.splitParent());
@@ -251,8 +251,8 @@
                 if (allocator.isProcessed(operand)) {
                     Interval interval = intervalAt(operand);
                     assert interval != null : "Could not find interval for operand " + operand;
-                    if (op.id != -1) {
-                        interval = interval.getSplitChildAtOpId(op.id, LIRInstruction.OperandMode.Temp, allocator);
+                    if (op.id() != -1) {
+                        interval = interval.getSplitChildAtOpId(op.id(), LIRInstruction.OperandMode.Temp, allocator);
                     }
 
                     statePut(inputState, interval.location(), interval.splitParent());
@@ -265,8 +265,8 @@
                 CiValue operand = op.operandAt(LIRInstruction.OperandMode.Output, j);
                 if (allocator.isProcessed(operand)) {
                     Interval interval = intervalAt(operand);
-                    if (op.id != -1) {
-                        interval = interval.getSplitChildAtOpId(op.id, LIRInstruction.OperandMode.Output, allocator);
+                    if (op.id() != -1) {
+                        interval = interval.getSplitChildAtOpId(op.id(), LIRInstruction.OperandMode.Output, allocator);
                     }
 
                     statePut(inputState, interval.location(), interval.splitParent());
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.java	Tue Jun 28 19:14:28 2011 +0200
@@ -479,7 +479,7 @@
             out.println("LIR");
             for (int i = 0; i < lir.length(); i++) {
                 LIRInstruction inst = lir.at(i);
-                out.printf("nr %4d ", inst.id).print(COLUMN_END);
+                out.printf("nr %4d ", inst.id()).print(COLUMN_END);
 
                 if (inst.info != null) {
                     int level = out.indentationLevel();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Tue Jun 28 19:14:28 2011 +0200
@@ -100,10 +100,12 @@
             new DeadCodeEliminationPhase().apply(graph);
         }
 
-        new EscapeAnalysisPhase(compilation, this).apply(graph);
-        new DeadCodeEliminationPhase().apply(graph);
-        new CanonicalizerPhase().apply(graph);
-        new DeadCodeEliminationPhase().apply(graph);
+        if (GraalOptions.EscapeAnalysis) {
+            new EscapeAnalysisPhase(compilation, this).apply(graph);
+            new DeadCodeEliminationPhase().apply(graph);
+            new CanonicalizerPhase().apply(graph);
+            new DeadCodeEliminationPhase().apply(graph);
+        }
 
         if (GraalOptions.OptLoops) {
             new LoopPhase().apply(graph);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java	Tue Jun 28 19:14:28 2011 +0200
@@ -30,13 +30,14 @@
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
-import com.sun.cri.ri.*;
 
 /**
  * The {@code NewArray} class is the base of all instructions that allocate arrays.
  */
 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;
 
@@ -154,7 +155,6 @@
                 assert x.array() == node;
                 return false;
             } else if (usage instanceof VirtualObject) {
-                VirtualObject x = (VirtualObject) usage;
                 return false;
             } else {
                 return true;
@@ -162,12 +162,24 @@
         }
 
         @Override
+        public EscapeField[] fields(Node node) {
+            NewArray x = (NewArray) node;
+            int length = x.dimension(0).asConstant().asInt();
+            EscapeField[] fields = new EscapeField[length];
+            for (int i = 0; i < length; i++) {
+                Integer representation = i;
+                fields[i] = new EscapeField("[" + i + "]", representation, ((NewArray) node).elementKind());
+            }
+            return fields;
+        }
+
+        @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.replace(guard.next());
+                    guard.replaceAndDelete(guard.next());
                 }
                 x.delete();
             } else if (usage instanceof IsType) {
@@ -175,30 +187,15 @@
                 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.replace(guard.next());
+                    guard.replaceAndDelete(guard.next());
                 }
                 x.delete();
             } else if (usage instanceof AccessMonitor) {
                 AccessMonitor x = (AccessMonitor) usage;
-                x.replace(x.next());
+                x.replaceAndDelete(x.next());
             } else if (usage instanceof ArrayLength) {
                 ArrayLength x = (ArrayLength) usage;
-                x.replace(((NewArray) node).dimension(0));
-            }
-        }
-
-        @Override
-        public void collectField(Node node, Node usage, Map<Object, EscapeField> fields) {
-            if (usage instanceof AccessIndexed) {
-                AccessIndexed x = (AccessIndexed) usage;
-                CiConstant index = x.index().asConstant();
-                CiConstant length = ((NewArray) node).dimension(0).asConstant();
-                assert index != null && length != null && index.asInt() >= 0 && index.asInt() < length.asInt();
-
-                Integer representation = index.asInt();
-                if (!fields.containsKey(representation)) {
-                    fields.put(representation, new EscapeField("[" + representation + "]", representation, ((NewArray) node).elementKind()));
-                }
+                x.replaceAndDelete(((NewArray) node).dimension(0));
             }
         }
 
@@ -215,14 +212,14 @@
                             usage.inputs().replace(x, fieldState.get(field));
                         }
                         assert x.usages().size() == 0;
-                        x.replace(x.next());
+                        x.replaceAndDelete(x.next());
                     }
                 } else if (current instanceof StoreIndexed) {
                     StoreIndexed x = (StoreIndexed) current;
                     if (x.array() == node) {
                         fieldState.put(field, x.value());
                         assert x.usages().size() == 0;
-                        x.replace(x.next());
+                        x.replaceAndDelete(x.next());
                     }
                 }
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Tue Jun 28 19:14:28 2011 +0200
@@ -138,7 +138,6 @@
                 assert x.object() == node;
                 return false;
             } else if (usage instanceof VirtualObject) {
-                VirtualObject x = (VirtualObject) usage;
                 return false;
             } else if (usage instanceof RegisterFinalizer) {
                 RegisterFinalizer x = (RegisterFinalizer) usage;
@@ -150,12 +149,24 @@
         }
 
         @Override
+        public EscapeField[] fields(Node node) {
+            NewInstance x = (NewInstance) node;
+            RiField[] riFields = x.instanceClass().fields();
+            EscapeField[] fields = new EscapeField[riFields.length];
+            for (int i = 0; i < riFields.length; i++) {
+                RiField field = riFields[i];
+                fields[i] = new EscapeField(field.name(), field, field.kind().stackKind());
+            }
+            return fields;
+        }
+
+        @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.replace(guard.next());
+                    guard.replaceAndDelete(guard.next());
                 }
                 x.delete();
             } else if (usage instanceof IsType) {
@@ -163,26 +174,15 @@
                 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.replace(guard.next());
+                    guard.replaceAndDelete(guard.next());
                 }
                 x.delete();
             } else if (usage instanceof AccessMonitor) {
                 AccessMonitor x = (AccessMonitor) usage;
-                x.replace(x.next());
+                x.replaceAndDelete(x.next());
             } else if (usage instanceof RegisterFinalizer) {
                 RegisterFinalizer x = (RegisterFinalizer) usage;
-                x.replace(x.next());
-            }
-        }
-
-        @Override
-        public void collectField(Node node, Node usage, Map<Object, EscapeField> fields) {
-             if (usage instanceof AccessField) {
-                 AccessField x = (AccessField) usage;
-                assert x.object() == node;
-                if (!fields.containsKey(x.field())) {
-                    fields.put(x.field(), new EscapeField(x.field().name(), x.field(), x.field.kind().stackKind()));
-                }
+                x.replaceAndDelete(x.next());
             }
         }
 
@@ -198,14 +198,14 @@
                             usage.inputs().replace(x, fieldState.get(field));
                         }
                         assert x.usages().size() == 0;
-                        x.replace(x.next());
+                        x.replaceAndDelete(x.next());
                     }
                 } else if (current instanceof StoreField) {
                     StoreField x = (StoreField) current;
                     if (x.object() == node) {
                         fieldState.put(field, x.value());
                         assert x.usages().size() == 0;
-                        x.replace(x.next());
+                        x.replaceAndDelete(x.next());
                     }
                 }
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObject.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObject.java	Tue Jun 28 19:14:28 2011 +0200
@@ -56,7 +56,7 @@
         return (VirtualObject) inputs().get(super.inputCount() + INPUT_OBJECT);
     }
 
-    public VirtualObject setObject(VirtualObject n) {
+    private VirtualObject setObject(VirtualObject n) {
         return (VirtualObject) inputs().set(super.inputCount() + INPUT_OBJECT, n);
     }
 
@@ -72,6 +72,7 @@
     }
 
     private EscapeField field;
+    private EscapeField[] fields;
     private RiType type;
 
     /**
@@ -79,11 +80,13 @@
      * @param array the instruction producing the array
      * @param newFrameState the state after executing this instruction
      */
-    public VirtualObject(VirtualObject object, EscapeField field, RiType type, Graph graph) {
+    public VirtualObject(VirtualObject object, Value input, EscapeField field, 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() {
@@ -94,6 +97,10 @@
         return type;
     }
 
+    public EscapeField[] fields() {
+        return fields;
+    }
+
     @Override
     public void accept(ValueVisitor v) {
         // nothing to do...
@@ -119,7 +126,7 @@
 
     @Override
     public Node copy(Graph into) {
-        VirtualObject x = new VirtualObject(null, field, type, into);
+        VirtualObject x = new VirtualObject(null, null, field, type, fields, into);
         return x;
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Tue Jun 28 19:14:28 2011 +0200
@@ -90,7 +90,7 @@
     /**
      * Value id for register allocation.
      */
-    public int id;
+    private int id;
 
     /**
      * Determines if all caller-saved registers are destroyed by this instruction.
@@ -198,6 +198,14 @@
         assert verifyOperands();
     }
 
+    public final int id() {
+        return id;
+    }
+
+    public final void setId(int id) {
+        this.id = id;
+    }
+
     private LIROperand initOutput(CiValue output) {
         assert output != null;
         if (output != CiValue.IllegalValue) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Tue Jun 28 19:14:28 2011 +0200
@@ -64,7 +64,7 @@
                     Boolean result = compare.condition().foldCondition(constX, constY, GraalCompilation.compilation().runtime);
                     if (result != null) {
                         Node actualSuccessor = result ? ifNode.trueSuccessor() : ifNode.falseSuccessor();
-                        ifNode.replace(actualSuccessor);
+                        ifNode.replaceAndDelete(actualSuccessor);
                     } else {
                         TTY.println("if not removed %s %s %s (%s %s)", constX, compare.condition(), constY, constX.kind, constY.kind);
                     }
@@ -74,7 +74,7 @@
         // remove unnecessary FixedGuards
         for (FixedGuard guard : graph.getNodes(FixedGuard.class)) {
             if (guard.node() instanceof IsNonNull && ((IsNonNull) guard.node()).object() instanceof NewInstance) {
-                guard.replace(guard.next());
+                guard.replaceAndDelete(guard.next());
             }
         }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Tue Jun 28 19:14:28 2011 +0200
@@ -42,6 +42,7 @@
 
     public static class BlockExitState {
         public final Map<EscapeField, Node> fieldState;
+        public VirtualObject obj;
 
         public BlockExitState() {
             this.fieldState = new HashMap<EscapeField, Node>();
@@ -57,6 +58,8 @@
         private final EscapeOp op;
         private Graph graph;
         private final Node node;
+        private RiType type;
+        private EscapeField[] escapeFields;
 
         public EscapementFixup(EscapeOp op, Graph graph, Node node) {
             this.op = op;
@@ -77,7 +80,11 @@
             final HashMap<Phi, EscapeField> phis = new HashMap<Phi, EscapeField>();
             final Block startBlock = identifyBlocksPhase.getNodeToBlock().get(node);
             assert startBlock != null;
-            final RiType type = ((Value) node).exactType();
+            type = ((Value) node).exactType();
+            escapeFields = op.fields(node);
+            for (EscapeField field : escapeFields) {
+                fields.put(field.representation(), field);
+            }
 
             Block.iteratePostOrder(blocks, new BlockClosure() {
 
@@ -95,8 +102,11 @@
 
                     BlockExitState state = new BlockExitState();
                     if (block == startBlock) {
+                        state.obj = null;
                         for (EscapeField field : fields.values()) {
-                            state.fieldState.put(field, Constant.defaultForKind(field.kind(), graph));
+                            Constant value = Constant.defaultForKind(field.kind(), graph);
+                            state.fieldState.put(field, value);
+                            state.obj = new VirtualObject(state.obj, value, field, type, escapeFields, graph);
                         }
                     } else {
                         List<Block> predecessors = block.getPredecessors();
@@ -122,6 +132,7 @@
                                 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);
                             }
                         }
                     }
@@ -133,12 +144,12 @@
                         current = block.firstNode();
                     }
                     while (current != block.lastNode()) {
-                        Node next = ((Instruction) current).next();
+                        Node next = ((FixedNodeWithNext) current).next();
                         op.updateState(node, current, fields, state.fieldState);
-                        if (!current.isDeleted() && current instanceof Instruction) {
-                            FrameState stateAfter = ((Instruction) current).stateAfter();
+                        if (!current.isDeleted() && current instanceof StateSplit) {
+                            FrameState stateAfter = ((StateSplit) current).stateAfter();
                             if (stateAfter != null) {
-                                updateFrameState(stateAfter, state, type, null);
+                                updateFrameState(stateAfter, state.obj);
                             }
                         }
                         current = next;
@@ -196,50 +207,38 @@
                 usage.inputs().replace(node, Node.Null);
             }
 
-            if (node instanceof Instruction) {
-                node.replace(((Instruction) node).next());
+            if (node instanceof FixedNodeWithNext) {
+                node.replaceAndDelete(((FixedNodeWithNext) node).next());
             } else {
                 node.delete();
             }
         }
 
-        private VirtualObject updateFrameState(FrameState frameState, BlockExitState currentState, RiType type, VirtualObject current) {
+        private VirtualObject updateFrameState(FrameState frameState, VirtualObject current) {
             for (int i = 0; i < frameState.inputs().size(); i++) {
                 if (frameState.inputs().get(i) == node) {
-                    if (current == null) {
-                        for (EscapeField field : fields.values()) {
-                            current = new VirtualObject(current, field, type, graph);
-                            current.setInput((Value) currentState.fieldState.get(field));
-                        }
-                    }
                     frameState.inputs().set(i, current);
                 } else if (frameState.inputs().get(i) instanceof VirtualObject) {
                     VirtualObject obj = (VirtualObject) frameState.inputs().get(i);
                     do {
-                        current = updateVirtualObject(obj, currentState, type, current);
+                        current = updateVirtualObject(obj, current);
                         obj = obj.object();
                     } while (obj != null);
                 }
             }
             if (frameState.outerFrameState() != null) {
-                current = updateFrameState(frameState.outerFrameState(), currentState, type, current);
+                current = updateFrameState(frameState.outerFrameState(), current);
             }
             return current;
         }
 
-        private VirtualObject updateVirtualObject(VirtualObject obj, BlockExitState currentState, RiType type, VirtualObject current) {
+        private VirtualObject updateVirtualObject(VirtualObject obj, VirtualObject current) {
             if (obj.input() == node) {
-                if (current == null) {
-                    for (EscapeField field : fields.values()) {
-                        current = new VirtualObject(current, field, type, graph);
-                        current.setInput((Value) currentState.fieldState.get(field));
-                    }
-                }
                 obj.setInput(current);
             } else if (obj.input() instanceof VirtualObject) {
                 VirtualObject obj2 = (VirtualObject) obj.input();
                 do {
-                    current = updateVirtualObject(obj2, currentState, type, current);
+                    current = updateVirtualObject(obj2, current);
                     obj2 = obj2.object();
                 } while (obj2 != null);
             }
@@ -249,9 +248,6 @@
         private void process() {
             for (Node usage : new ArrayList<Node>(node.usages())) {
                 op.beforeUpdate(node, usage);
-                if (!usage.isDeleted()) {
-                    op.collectField(node, usage, fields);
-                }
             }
         }
     }
@@ -283,7 +279,7 @@
                     weight = analyze(op, node, exits, invokes);
                     if (exits.size() != 0) {
                         if (GraalOptions.TraceEscapeAnalysis) {
-                            TTY.println("####### escaping object: %d %s in %s", node.id(), node.shortName(), compilation.method);
+                            TTY.println("####### escaping object: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method);
                             TTY.print("%d: new value: %d %s, weight %d, escapes at ", iterations, node.id(), node.shortName(), weight);
                             for (Node n : exits) {
                                 TTY.print("%d %s, ", n.id(), n.shortName());
@@ -297,7 +293,7 @@
                     }
                     if (invokes.size() == 0) {
                         if (GraalOptions.TraceEscapeAnalysis) {
-                            TTY.println("!!!!!!!! non-escaping object: %d %s in %s", node.id(), node.shortName(), compilation.method);
+                            TTY.println("!!!!!!!! non-escaping object: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method);
                         }
                         new EscapementFixup(op, graph, node).apply();
                         new PhiSimplifier(graph);
@@ -375,9 +371,9 @@
 
         boolean escape(Node node, Node usage);
 
-        void beforeUpdate(Node node, Node usage);
+        EscapeField[] fields(Node node);
 
-        void collectField(Node node, Node usage, Map<Object, EscapeField> fields);
+        void beforeUpdate(Node node, Node usage);
 
         void updateState(Node node, Node current, Map<Object, EscapeField> fields, Map<EscapeField, Node> fieldState);
 
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypePrimitive.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypePrimitive.java	Tue Jun 28 19:14:28 2011 +0200
@@ -150,4 +150,8 @@
         return null;
     }
 
+    @Override
+    public RiField[] fields() {
+        return null;
+    }
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl.java	Tue Jun 28 19:14:28 2011 +0200
@@ -222,4 +222,8 @@
         return ((HotSpotMethodResolved) method).uniqueConcreteMethod();
     }
 
+    @Override
+    public RiField[] fields() {
+        return compiler.getVMEntries().RiType_fields(this);
+    }
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeUnresolved.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeUnresolved.java	Tue Jun 28 19:14:28 2011 +0200
@@ -201,4 +201,8 @@
         throw unresolved("uniqueConcreteMethod");
     }
 
+    @Override
+    public RiField[] fields() {
+        return null;
+    }
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java	Tue Jun 28 19:14:28 2011 +0200
@@ -87,9 +87,9 @@
 
     void recordBailout(String reason);
 
-    RiType RiType_uniqueConcreteSubtype(HotSpotTypeResolved hotSpotTypeResolved);
+    RiType RiType_uniqueConcreteSubtype(HotSpotTypeResolved klass);
 
-    RiType RiType_superType(HotSpotTypeResolved hotSpotTypeResolved);
+    RiType RiType_superType(HotSpotTypeResolved klass);
 
     int getArrayLength(CiConstant array);
 
@@ -97,5 +97,7 @@
 
     RiType getRiType(CiConstant constant);
 
+    RiField[] RiType_fields(HotSpotTypeResolved klass);
+
     // Checkstyle: resume
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java	Mon Jun 27 17:15:12 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java	Tue Jun 28 19:14:28 2011 +0200
@@ -141,5 +141,8 @@
         return getType(o.getClass());
     }
 
+    @Override
+    public native RiField[] RiType_fields(HotSpotTypeResolved klass);
+
     // Checkstyle: resume
 }
--- a/src/share/vm/classfile/systemDictionary.hpp	Mon Jun 27 17:15:12 2011 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Tue Jun 28 19:14:28 2011 +0200
@@ -209,10 +209,12 @@
   template(CiRegister_klass,             com_sun_cri_ci_CiRegister,                                 Opt) \
   template(CiCodePos_klass,              com_sun_cri_ci_CiCodePos,                                  Opt) \
   template(CiConstant_klass,             com_sun_cri_ci_CiConstant,                                 Opt) \
+  template(CiVirtualObject_klass,        com_sun_cri_ci_CiVirtualObject,                            Opt) \
   template(CiKind_klass,                 com_sun_cri_ci_CiKind,                                     Opt) \
   template(CiRuntimeCall_klass,          com_sun_cri_ci_CiRuntimeCall,                              Opt) \
   template(RiMethod_klass,               com_sun_cri_ri_RiMethod,                                   Opt) \
   template(RiType_klass,                 com_sun_cri_ri_RiType,                                     Opt) \
+  template(RiField_klass,                com_sun_cri_ri_RiField,                                    Opt) \
   template(RiExceptionHandler_klass,     com_sun_cri_ri_RiExceptionHandler,                         Opt) \
   template(RiTypeProfile_klass,          com_sun_cri_ri_RiTypeProfile,                              Opt) \
 
--- a/src/share/vm/classfile/vmSymbols.hpp	Mon Jun 27 17:15:12 2011 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Tue Jun 28 19:14:28 2011 +0200
@@ -258,18 +258,18 @@
   LP64_ONLY( do_alias(machine_word_signature,         long_signature) )                           \
                                                                                                                         \
   /* support for graal */                                                                                               \
-  template(com_sun_hotspot_graal_VMExits,               "com/oracle/max/graal/runtime/VMExits")                         \
+  template(com_sun_hotspot_graal_VMExits,             "com/oracle/max/graal/runtime/VMExits")                           \
   template(com_sun_hotspot_graal_HotSpotMethodResolved, "com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl")       \
-  template(com_sun_hotspot_graal_HotSpotTargetMethod,   "com/oracle/max/graal/runtime/HotSpotTargetMethod")             \
-  template(com_sun_hotspot_graal_HotSpotField,          "com/oracle/max/graal/runtime/HotSpotField")                    \
-  template(com_sun_graal_graalOptions,                    "com/sun/graal/graalOptions")                                 \
-  template(com_sun_hotspot_graal_HotSpotOptions,        "com/oracle/max/graal/runtime/HotSpotOptions")                  \
-  template(com_sun_hotspot_graal_HotSpotTypeResolved,   "com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl")         \
-  template(com_sun_hotspot_graal_HotSpotType,           "com/oracle/max/graal/runtime/HotSpotType")                     \
+  template(com_sun_hotspot_graal_HotSpotTargetMethod, "com/oracle/max/graal/runtime/HotSpotTargetMethod")               \
+  template(com_sun_hotspot_graal_HotSpotField,        "com/oracle/max/graal/runtime/HotSpotField")                      \
+  template(com_sun_graal_graalOptions,                "com/sun/graal/graalOptions")                                     \
+  template(com_sun_hotspot_graal_HotSpotOptions,      "com/oracle/max/graal/runtime/HotSpotOptions")                    \
+  template(com_sun_hotspot_graal_HotSpotTypeResolved, "com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl")           \
+  template(com_sun_hotspot_graal_HotSpotType,         "com/oracle/max/graal/runtime/HotSpotType")                       \
   template(com_sun_hotspot_graal_HotSpotExceptionHandler,"com/oracle/max/graal/runtime/HotSpotExceptionHandler")        \
-  template(com_sun_hotspot_graal_HotSpotProxy,          "com/oracle/max/graal/runtime/HotSpotProxy")                    \
-  template(com_sun_hotspot_graal_Compiler,              "com/oracle/max/graal/runtime/Compiler")                        \
-  template(com_sun_hotspot_graal_CompilerImpl,          "com/oracle/max/graal/runtime/CompilerImpl")                    \
+  template(com_sun_hotspot_graal_HotSpotProxy,        "com/oracle/max/graal/runtime/HotSpotProxy")                      \
+  template(com_sun_hotspot_graal_Compiler,            "com/oracle/max/graal/runtime/Compiler")                          \
+  template(com_sun_hotspot_graal_CompilerImpl,        "com/oracle/max/graal/runtime/CompilerImpl")                      \
   template(com_sun_cri_ri_RiMethod,                   "com/sun/cri/ri/RiMethod")                                        \
   template(com_sun_cri_ri_RiField,                    "com/sun/cri/ri/RiField")                                         \
   template(com_sun_cri_ri_RiType,                     "com/sun/cri/ri/RiType")                                          \
@@ -278,7 +278,7 @@
   template(com_sun_cri_ri_RiExceptionHandler,         "com/sun/cri/ri/RiExceptionHandler")                              \
   template(com_sun_cri_ci_CiAssumptions,              "com/sun/cri/ci/CiAssumptions")                                   \
   template(com_sun_cri_ci_CiAssumptions_ConcreteSubtype, "com/sun/cri/ci/CiAssumptions$ConcreteSubtype")                \
-  template(com_sun_cri_ci_CiAssumptions_ConcreteMethod,  "com/sun/cri/ci/CiAssumptions$ConcreteMethod")                 \
+  template(com_sun_cri_ci_CiAssumptions_ConcreteMethod, "com/sun/cri/ci/CiAssumptions$ConcreteMethod")                  \
   template(com_sun_cri_ci_CiTargetMethod,             "com/sun/cri/ci/CiTargetMethod")                                  \
   template(com_sun_cri_ci_CiTargetMethod_Site,        "com/sun/cri/ci/CiTargetMethod$Site")                             \
   template(com_sun_cri_ci_CiTargetMethod_Call,        "com/sun/cri/ci/CiTargetMethod$Call")                             \
@@ -295,6 +295,7 @@
   template(com_sun_cri_ci_CiRegister,                 "com/sun/cri/ci/CiRegister")                                      \
   template(com_sun_cri_ci_CiCodePos,                  "com/sun/cri/ci/CiCodePos")                                       \
   template(com_sun_cri_ci_CiConstant,                 "com/sun/cri/ci/CiConstant")                                      \
+  template(com_sun_cri_ci_CiVirtualObject,            "com/sun/cri/ci/CiVirtualObject")                                 \
   template(com_sun_cri_ci_CiKind,                     "com/sun/cri/ci/CiKind")                                          \
   template(com_sun_cri_ci_CiRuntimeCall,              "com/sun/cri/ci/CiRuntimeCall")                                   \
   template(startCompiler_name,                        "startCompiler")                                                  \
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Mon Jun 27 17:15:12 2011 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Tue Jun 28 19:14:28 2011 +0200
@@ -107,7 +107,7 @@
 }
 
 // TODO: finish this - graal doesn't provide any scope values at the moment
-static ScopeValue* get_hotspot_value(oop value, int frame_size, ScopeValue* &second) {
+static ScopeValue* get_hotspot_value(oop value, int frame_size, GrowableArray<ScopeValue*>* objects, ScopeValue* &second) {
   second = NULL;
   if (value == CiValue::IllegalValue()) {
     return new LocationValue(Location::new_stk_loc(Location::invalid, 0));
@@ -182,6 +182,45 @@
       return new ConstantLongValue(prim);
     }
     tty->print("%i", type);
+  } else if (value->is_a(CiVirtualObject::klass())) {
+    oop type = CiVirtualObject::type(value);
+    int id = CiVirtualObject::id(value);
+    ciKlass* klass = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)));
+    assert(klass->is_instance_klass() || klass->is_array_klass(), "Not supported allocation.");
+
+    for (jint i = 0; i < objects->length(); i++) {
+      ObjectValue* obj = (ObjectValue*) objects->at(i);
+      if (obj->id() == id) {
+        return obj;
+      }
+    }
+
+    ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(klass->constant_encoding()));
+
+    arrayOop values = (arrayOop) CiVirtualObject::values(value);
+    for (jint i = 0; i < values->length(); i++) {
+      ((oop*) values->base(T_OBJECT))[i];
+    }
+
+    for (jint i = 0; i < values->length(); i++) {
+      ScopeValue* second = NULL;
+      ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], frame_size, objects, second);
+
+//      if (second != NULL) {
+//        sv->field_values()->append(second);
+//      }
+      sv->field_values()->append(value);
+    }
+
+//    uint first_ind = spobj->first_index();
+//    for (uint i = 0; i < spobj->n_fields(); i++) {
+//      Node* fld_node = sfn->in(first_ind+i);
+//      (void)FillLocArray(sv->field_values()->length(), sfn, fld_node, sv->field_values(), objs);
+//    }
+//    scval = sv;
+
+    objects->append(sv);
+    return sv;
   } else {
     value->klass()->print();
     value->print();
@@ -421,10 +460,10 @@
 
 }
 
-void CodeInstaller::record_scope(jint pc_offset, oop code_pos) {
+void CodeInstaller::record_scope(jint pc_offset, oop code_pos, GrowableArray<ScopeValue*>* objects) {
   oop caller_pos = CiCodePos::caller(code_pos);
   if (caller_pos != NULL) {
-    record_scope(pc_offset, caller_pos);
+    record_scope(pc_offset, caller_pos, objects);
   }
   oop frame = NULL;
   if (code_pos->klass()->klass_part()->name() == vmSymbols::com_sun_cri_ci_CiFrame()) {
@@ -466,7 +505,7 @@
 
     for (jint i = 0; i < values->length(); i++) {
       ScopeValue* second = NULL;
-      ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], _frame_size, second);
+      ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], _frame_size, objects, second);
 
       if (i < local_count) {
         if (second != NULL) {
@@ -492,6 +531,9 @@
         assert(((oop*) values->base(T_OBJECT))[i] == CiValue::IllegalValue(), "double-slot value not followed by CiValue.IllegalValue");
       }
     }
+
+    _debug_recorder->dump_object_pool(objects);
+
     DebugToken* locals_token = _debug_recorder->create_scope_values(locals);
     DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions);
     DebugToken* monitors_token = _debug_recorder->create_monitor_values(monitors);
@@ -516,7 +558,7 @@
   _debug_recorder->add_safepoint(pc_offset, create_oop_map(_frame_size, _parameter_count, debug_info));
 
   oop code_pos = CiDebugInfo::codePos(debug_info);
-  record_scope(pc_offset, code_pos);
+  record_scope(pc_offset, code_pos, new GrowableArray<ScopeValue*>());
 
   _debug_recorder->end_safepoint(pc_offset);
 }
@@ -537,7 +579,7 @@
   if (debug_info != NULL) {
     _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_frame_size, _parameter_count, debug_info));
     oop code_pos = CiDebugInfo::codePos(debug_info);
-    record_scope(next_pc_offset, code_pos);
+    record_scope(next_pc_offset, code_pos, new GrowableArray<ScopeValue*>());
   }
 
   if (runtime_call != NULL) {
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Mon Jun 27 17:15:12 2011 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Tue Jun 28 19:14:28 2011 +0200
@@ -99,7 +99,7 @@
   void site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site);
   void site_Mark(CodeBuffer& buffer, jint pc_offset, oop site);
 
-  void record_scope(jint pc_offset, oop code_pos);
+  void record_scope(jint pc_offset, oop code_pos, GrowableArray<ScopeValue*>* objects);
 
   void process_exception_handlers();
 
--- a/src/share/vm/graal/graalCompiler.cpp	Mon Jun 27 17:15:12 2011 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Tue Jun 28 19:14:28 2011 +0200
@@ -144,8 +144,13 @@
 }
 
 oop GraalCompiler::get_RiField(ciField *field, ciInstanceKlass* accessor_klass, KlassHandle accessor, Bytecodes::Code byteCode, TRAPS) {
-  bool will_link = field->will_link_from_vm(accessor_klass, byteCode);
-  int offset = (field->holder()->is_loaded() && will_link) ? field->offset() : -1;
+  int offset;
+  if (byteCode != Bytecodes::_illegal) {
+    bool will_link = field->will_link_from_vm(accessor_klass, byteCode);
+    offset = (field->holder()->is_loaded() && will_link) ? field->offset() : -1;
+  } else {
+    offset = field->offset();
+  }
   Handle field_name = VmIds::toString<Handle>(field->name()->get_symbol(), CHECK_0);
   Handle field_holder = get_RiType(field->holder(), accessor, CHECK_0);
   Handle field_type = get_RiType(field->type(), accessor, CHECK_0);
--- a/src/share/vm/graal/graalJavaAccess.hpp	Mon Jun 27 17:15:12 2011 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Tue Jun 28 19:14:28 2011 +0200
@@ -207,6 +207,11 @@
   start_class(CiStackSlot)                                                              \
     int_field(CiStackSlot, index)                                                       \
   end_class                                                                             \
+  start_class(CiVirtualObject)                                                          \
+    int_field(CiVirtualObject, id)                                                      \
+    oop_field(CiVirtualObject, type, "Lcom/sun/cri/ri/RiType;")                         \
+    oop_field(CiVirtualObject, values, "[Lcom/sun/cri/ci/CiValue;")                     \
+  end_class                                                                             \
   start_class(RiTypeProfile)                                                            \
     int_field(RiTypeProfile, count)                                                     \
     int_field(RiTypeProfile, morphism)                                                  \
--- a/src/share/vm/graal/graalVMEntries.cpp	Mon Jun 27 17:15:12 2011 +0200
+++ b/src/share/vm/graal/graalVMEntries.cpp	Tue Jun 28 19:14:28 2011 +0200
@@ -631,6 +631,31 @@
   return JNIHandles::make_local(THREAD, GraalCompiler::createHotSpotTypeResolved(array, name, THREAD));
 }
 
+// public RiField[] RiType_fields(HotSpotTypeResolved klass);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1fields(JNIEnv *, jobject, jobject klass) {
+  TRACE_graal_3("VMEntries::RiType_fields");
+  KlassHandle klass_handle;
+  ciInstanceKlass* instance_klass;
+  {
+    VM_ENTRY_MARK;
+    klass_handle = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass));
+    instance_klass = (ciInstanceKlass*) CURRENT_ENV->get_object(klass_handle());
+  }
+  GrowableArray<ciField*>* fields = instance_klass->non_static_fields();
+
+  objArrayHandle fieldsArray;
+  {
+    VM_ENTRY_MARK;
+    fieldsArray = oopFactory::new_objArray(SystemDictionary::RiField_klass(), fields->length(), CHECK_NULL);
+    for (int i = 0; i < fields->length(); i++) {
+      ciField* field = fields->at(i);
+      Handle field_handle = GraalCompiler::get_RiField(field, instance_klass, klass_handle, Bytecodes::_illegal, CHECK_NULL);
+      fieldsArray->obj_at_put(i, field_handle());
+    }
+  }
+  return JNIHandles::make_local(fieldsArray());
+}
+
 // public RiType getPrimitiveArrayType(CiKind kind);
 JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_getPrimitiveArrayType(JNIEnv *env, jobject, jobject kind) {
   TRACE_graal_3("VMEntries::VMEntries_getPrimitiveArrayType");
@@ -847,6 +872,7 @@
   {CC"RiType_uniqueConcreteSubtype",    CC"("RESOLVED_TYPE")"TYPE,                  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1uniqueConcreteSubtype)},
   {CC"RiType_superType",                CC"("RESOLVED_TYPE")"TYPE,                  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1superType)},
   {CC"RiType_arrayOf",                  CC"("RESOLVED_TYPE")"TYPE,                  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1arrayOf)},
+  {CC"RiType_fields",                   CC"("RESOLVED_TYPE")["FIELD,                FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1fields)},
   {CC"RiType_isInitialized",            CC"("RESOLVED_TYPE")Z",                     FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1isInitialized)},
   {CC"getPrimitiveArrayType",           CC"("CI_KIND")"TYPE,                        FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getPrimitiveArrayType)},
   {CC"getType",                         CC"("CLASS")"TYPE,                          FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getType)},
--- a/src/share/vm/runtime/deoptimization.cpp	Mon Jun 27 17:15:12 2011 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Tue Jun 28 19:14:28 2011 +0200
@@ -206,11 +206,11 @@
   assert(vf->is_compiled_frame(), "Wrong frame type");
   chunk->push(compiledVFrame::cast(vf));
 
-#ifdef COMPILER2
+//#ifdef COMPILER2
   // Reallocate the non-escaping objects and restore their fields. Then
   // relock objects if synchronization on them was eliminated.
-  if (DoEscapeAnalysis) {
-    if (EliminateAllocations) {
+//  if (DoEscapeAnalysis) {
+//    if (EliminateAllocations) {
       assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames");
       GrowableArray<ScopeValue*>* objects = chunk->at(0)->scope()->objects();
 
@@ -254,8 +254,8 @@
         // Restore result.
         deoptee.set_saved_oop_result(&map, return_value());
       }
-    }
-    if (EliminateLocks) {
+//    }
+//    if (EliminateLocks) {
 #ifndef PRODUCT
       bool first = true;
 #endif
@@ -282,9 +282,9 @@
 #endif
         }
       }
-    }
-  }
-#endif // COMPILER2
+//    }
+//  }
+//#endif // COMPILER2
   // Ensure that no safepoint is taken after pointers have been stored
   // in fields of rematerialized objects.  If a safepoint occurs from here on
   // out the java state residing in the vframeArray will be missed.
@@ -709,7 +709,7 @@
 }
 
 
-#ifdef COMPILER2
+//#ifdef COMPILER2
 bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS) {
   Handle pending_exception(thread->pending_exception());
   const char* exception_file = thread->exception_file();
@@ -951,7 +951,7 @@
   }
 }
 #endif
-#endif // COMPILER2
+//#endif // COMPILER2
 
 vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk) {
 
--- a/src/share/vm/runtime/deoptimization.hpp	Mon Jun 27 17:15:12 2011 +0200
+++ b/src/share/vm/runtime/deoptimization.hpp	Tue Jun 28 19:14:28 2011 +0200
@@ -109,7 +109,7 @@
   // executing in a particular CodeBlob if UseBiasedLocking is enabled
   static void revoke_biases_of_monitors(CodeBlob* cb);
 
-#ifdef COMPILER2
+//#ifdef COMPILER2
   // Support for restoring non-escaping objects
   static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS);
   static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type);
@@ -117,7 +117,7 @@
   static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects);
   static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread);
   NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects);)
-#endif // COMPILER2
+//#endif // COMPILER2
 
   public:
   static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk);