changeset 5139:ee615aee55b4

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Wed, 21 Mar 2012 14:32:47 +0100
parents 4d8ebb0fc484 (current diff) e1a03c81cef0 (diff)
children 5f79c8ebc5dc
files
diffstat 50 files changed, 519 insertions(+), 204 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Wed Mar 21 14:32:47 2012 +0100
@@ -43,9 +43,9 @@
 
     private HashMap<VirtualObjectNode, CiVirtualObject> virtualObjects = new HashMap<>();
 
-    public LIRDebugInfo build(FrameState topState, LockScope locks, List<CiStackSlot> pointerSlots, LabelRef exceptionEdge) {
+    public LIRDebugInfo build(FrameState topState, LockScope locks, List<CiStackSlot> pointerSlots, LabelRef exceptionEdge, long leafGraphId) {
         assert virtualObjects.size() == 0;
-        CiFrame frame = computeFrameForState(topState, locks);
+        CiFrame frame = computeFrameForState(topState, locks, leafGraphId);
 
         CiVirtualObject[] virtualObjectsArray = null;
         if (virtualObjects.size() != 0) {
@@ -106,7 +106,7 @@
         return new LIRDebugInfo(frame, virtualObjectsArray, pointerSlots, exceptionEdge);
     }
 
-    private CiFrame computeFrameForState(FrameState state, LockScope locks) {
+    private CiFrame computeFrameForState(FrameState state, LockScope locks, long leafGraphId) {
         int numLocals = state.localsSize();
         int numStack = state.stackSize();
         int numLocks = (locks != null && locks.callerState == state.outerFrameState()) ? locks.stateDepth + 1 : 0;
@@ -133,14 +133,14 @@
 
         CiFrame caller = null;
         if (state.outerFrameState() != null) {
-            caller = computeFrameForState(state.outerFrameState(), nextLock);
+            caller = computeFrameForState(state.outerFrameState(), nextLock, -1);
         } else {
             if (nextLock != null) {
                 throw new CiBailout("unbalanced monitors: found monitor for unknown frame");
             }
         }
         assert state.bci >= 0 || state.bci == FrameState.BEFORE_BCI;
-        CiFrame frame = new CiFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, state.localsSize(), state.stackSize(), numLocks);
+        CiFrame frame = new CiFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, state.localsSize(), state.stackSize(), numLocks, leafGraphId);
         return frame;
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Mar 21 14:32:47 2012 +0100
@@ -248,15 +248,20 @@
 
     public LIRDebugInfo state() {
         assert lastState != null : "must have state before instruction";
-        return stateFor(lastState);
+        return stateFor(lastState, -1);
     }
 
-    public LIRDebugInfo stateFor(FrameState state) {
-        return stateFor(state, null, null);
+    public LIRDebugInfo state(long leafGraphId) {
+        assert lastState != null : "must have state before instruction";
+        return stateFor(lastState, leafGraphId);
     }
 
-    public LIRDebugInfo stateFor(FrameState state, List<CiStackSlot> pointerSlots, LabelRef exceptionEdge) {
-        return debugInfoBuilder.build(state, curLocks, pointerSlots, exceptionEdge);
+    public LIRDebugInfo stateFor(FrameState state, long leafGraphId) {
+        return stateFor(state, null, null, leafGraphId);
+    }
+
+    public LIRDebugInfo stateFor(FrameState state, List<CiStackSlot> pointerSlots, LabelRef exceptionEdge, long leafGraphId) {
+        return debugInfoBuilder.build(state, curLocks, pointerSlots, exceptionEdge, leafGraphId);
     }
 
     /**
@@ -527,7 +532,7 @@
         // The state before the monitor enter is used for null checks, so it must not contain the newly locked object.
         curLocks = new LockScope(curLocks, x.stateAfter().outerFrameState(), x, lockData);
         // The state after the monitor enter is used for deoptimization, after the monitor has blocked, so it must contain the newly locked object.
-        LIRDebugInfo stateAfter = stateFor(x.stateAfter());
+        LIRDebugInfo stateAfter = stateFor(x.stateAfter(), -1);
 
         XirSnippet snippet = xir.genMonitorEnter(site(x, x.object()), obj, lockAddress);
         emitXir(snippet, x, stateBefore, stateAfter, true, null, null);
@@ -744,20 +749,21 @@
     }
 
     @Override
-    public void emitGuardCheck(BooleanNode comp, RiDeoptReason deoptReason) {
+    public void emitGuardCheck(BooleanNode comp, RiDeoptReason deoptReason, long leafGraphId) {
         if (comp instanceof NullCheckNode && !((NullCheckNode) comp).expectedNull) {
-            emitNullCheckGuard((NullCheckNode) comp);
+            emitNullCheckGuard((NullCheckNode) comp, leafGraphId);
         } else if (comp instanceof ConstantNode && comp.asConstant().asBoolean()) {
             // True constant, nothing to emit.
+            // False constants are handled within emitBranch.
         } else {
             // Fall back to a normal branch.
-            LIRDebugInfo info = state();
+            LIRDebugInfo info = state(leafGraphId);
             LabelRef stubEntry = createDeoptStub(RiDeoptAction.InvalidateReprofile, deoptReason, info, comp);
             emitBranch(comp, null, stubEntry, info);
         }
     }
 
-    protected abstract void emitNullCheckGuard(NullCheckNode node);
+    protected abstract void emitNullCheckGuard(NullCheckNode node, long leafGraphId);
 
     public void emitBranch(BooleanNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) {
         if (node instanceof NullCheckNode) {
@@ -925,7 +931,7 @@
         if (!target().invokeSnippetAfterArguments) {
             // This is the version currently necessary for Maxine: since the invokeinterface-snippet uses a division, it
             // destroys rdx, which is also used to pass a parameter.  Therefore, the snippet must be before the parameters are assigned to their locations.
-            LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()));
+            LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), x.leafGraphId());
             destinationAddress = emitXir(snippet, x.node(), addrInfo, false);
         }
 
@@ -938,11 +944,11 @@
 
         if (target().invokeSnippetAfterArguments) {
             // This is the version currently active for HotSpot.
-            LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), null, null);
+            LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), null, null, x.leafGraphId());
             destinationAddress = emitXir(snippet, x.node(), addrInfo, false);
         }
 
-        LIRDebugInfo callInfo = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null);
+        LIRDebugInfo callInfo = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null, x.leafGraphId());
         emitCall(targetMethod, resultOperand, argList, destinationAddress, callInfo, snippet.marks);
 
         if (isLegal(resultOperand)) {
@@ -1045,7 +1051,7 @@
             }
 
             // TODO is it correct here that the pointerSlots are not passed to the oop map generation?
-            info = stateFor(stateBeforeReturn);
+            info = stateFor(stateBeforeReturn, -1);
         }
 
         emitCall(x.call(), resultOperand, argList, CiConstant.forLong(0), info, null);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java	Wed Mar 21 14:32:47 2012 +0100
@@ -84,7 +84,7 @@
             }
             BeginNode ifBlockBegin = findBeginNode(ifNode);
             Debug.log("Converting %s on %-5s branch of %s to guard for remaining branch %s. IfBegin=%s", deopt, deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin, ifBlockBegin);
-            FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.reason()));
+            FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.reason(), deopt.leafGraphId()));
             otherBegin.replaceAtUsages(ifBlockBegin);
             FixedNode next = otherBegin.next();
             otherBegin.setNext(null);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Wed Mar 21 14:32:47 2012 +0100
@@ -60,7 +60,7 @@
             }
 
             @Override
-            public Node createGuard(Node condition, RiDeoptReason deoptReason) {
+            public Node createGuard(Node condition, RiDeoptReason deoptReason, long leafGraphId) {
                 // TODO (thomaswue): Document why this must not be called on floating nodes.
                 throw new UnsupportedOperationException();
             }
@@ -118,7 +118,7 @@
             }
 
             @Override
-            public Node createGuard(Node condition, RiDeoptReason deoptReason) {
+            public Node createGuard(Node condition, RiDeoptReason deoptReason, long leafGraphId) {
                 FixedNode guardAnchor = (FixedNode) getGuardAnchor();
                 if (GraalOptions.OptEliminateGuards) {
                     for (Node usage : condition.usages()) {
@@ -127,7 +127,7 @@
                         }
                     }
                 }
-                GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor, deoptReason));
+                GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor, deoptReason, leafGraphId));
                 activeGuards.grow();
                 activeGuards.mark(newGuard);
                 return newGuard;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Mar 21 14:32:47 2012 +0100
@@ -500,13 +500,18 @@
 
     @Override
     public void emitDeoptimizeOn(Condition cond, RiDeoptAction action, RiDeoptReason reason, Object deoptInfo) {
+        assert cond != null;
         LIRDebugInfo info = state();
         LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo);
-        if (cond != null) {
-            append(new BranchOp(cond, stubEntry, info));
-        } else {
-            append(new JumpOp(stubEntry, info));
-        }
+        append(new BranchOp(cond, stubEntry, info));
+    }
+
+
+    @Override
+    public void emitDeoptimize(RiDeoptAction action, RiDeoptReason reason, Object deoptInfo, long leafGraphId) {
+        LIRDebugInfo info = state(leafGraphId);
+        LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo);
+        append(new JumpOp(stubEntry, info));
     }
 
     @Override
@@ -554,10 +559,10 @@
     }
 
     @Override
-    protected void emitNullCheckGuard(NullCheckNode node) {
+    protected void emitNullCheckGuard(NullCheckNode node, long leafGraphId) {
         assert !node.expectedNull;
         Variable value = load(operand(node.object()));
-        LIRDebugInfo info = state();
+        LIRDebugInfo info = state(leafGraphId);
         append(new NullCheckOp(value, info));
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Wed Mar 21 14:32:47 2012 +0100
@@ -175,7 +175,7 @@
             ValueNode receiver = invoke.callTarget().receiver();
             ReadHubNode objectClass = graph.add(new ReadHubNode(receiver));
             IsTypeNode isTypeNode = graph.unique(new IsTypeNode(objectClass, type));
-            FixedGuardNode guard = graph.add(new FixedGuardNode(isTypeNode, RiDeoptReason.TypeCheckedInliningViolated));
+            FixedGuardNode guard = graph.add(new FixedGuardNode(isTypeNode, RiDeoptReason.TypeCheckedInliningViolated, invoke.leafGraphId()));
             AnchorNode anchor = graph.add(new AnchorNode());
             assert invoke.predecessor() != null;
 
@@ -303,7 +303,7 @@
             if (shouldFallbackToInvoke()) {
                 unknownTypeNode = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, 1, notRecordedTypeProbability, false);
             } else {
-                unknownTypeNode = graph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.TypeCheckedInliningViolated));
+                unknownTypeNode = graph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.TypeCheckedInliningViolated, invoke.leafGraphId()));
             }
 
             // replace the invoke exception edge
@@ -368,7 +368,7 @@
             ReadHubNode objectClassNode = graph.add(new ReadHubNode(invoke.callTarget().receiver()));
             graph.addBeforeFixed(invoke.node(), objectClassNode);
 
-            FixedNode unknownTypeNode = graph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.TypeCheckedInliningViolated));
+            FixedNode unknownTypeNode = graph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.TypeCheckedInliningViolated, invoke.leafGraphId()));
             FixedNode dispatchOnType = createDispatchOnType(graph, objectClassNode, new BeginNode[] {calleeEntryNode}, unknownTypeNode);
 
             FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor();
@@ -820,7 +820,7 @@
         } else {
             if (unwindNode != null) {
                 UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode);
-                DeoptimizeNode deoptimizeNode = new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.NotCompiledExceptionHandler);
+                DeoptimizeNode deoptimizeNode = new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.NotCompiledExceptionHandler, invoke.leafGraphId());
                 unwindDuplicate.replaceAndDelete(graph.add(deoptimizeNode));
                 // move the deopt upwards if there is a monitor exit that tries to use the "after exception" frame state
                 // (because there is no "after exception" frame state!)
@@ -908,7 +908,7 @@
         NodeInputList<ValueNode> parameters = callTarget.arguments();
         ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0);
         if (!callTarget.isStatic() && firstParam.kind() == CiKind.Object && !firstParam.stamp().nonNull()) {
-            graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new NullCheckNode(firstParam, false)), RiDeoptReason.ClassCastException)));
+            graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new NullCheckNode(firstParam, false)), RiDeoptReason.ClassCastException, invoke.leafGraphId())));
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Wed Mar 21 14:32:47 2012 +0100
@@ -39,7 +39,7 @@
     private final String meterFilter;
     private final String timerFilter;
     private final String dumpFilter;
-    private final String[] methodFilter;
+    private final MethodFilter[] methodFilter;
     private final List<DebugDumpHandler> dumpHandlers = new ArrayList<>();
 
     public HotSpotDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter) {
@@ -47,7 +47,15 @@
         this.meterFilter = meterFilter;
         this.timerFilter = timerFilter;
         this.dumpFilter = dumpFilter;
-        this.methodFilter = methodFilter == null ? null : methodFilter.split(",");
+        if (methodFilter == null || methodFilter.isEmpty()) {
+            this.methodFilter = null;
+        } else {
+            String[] filters = methodFilter.split(",");
+            this.methodFilter = new MethodFilter[filters.length];
+            for (int i = 0; i < filters.length; i++) {
+                this.methodFilter[i] = new MethodFilter(filters[i]);
+            }
+        }
         if (GraalOptions.PrintIdealGraphFile) {
             dumpHandlers.add(new IdealGraphPrinterDumpHandler());
         } else {
@@ -93,9 +101,8 @@
         } else {
             for (Object o : Debug.context()) {
                 if (o instanceof RiMethod) {
-                    String methodName = CiUtil.format("%H.%n", (RiMethod) o);
-                    for (String filter : methodFilter) {
-                        if (methodName.contains(filter)) {
+                    for (MethodFilter filter : methodFilter) {
+                        if (filter.matches((RiMethod) o)) {
                             return true;
                         }
                     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/MethodFilter.java	Wed Mar 21 14:32:47 2012 +0100
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot;
+
+import java.util.regex.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+
+/**
+ * This class implements a method filter that can filter based on class name, method name and parameters.
+ * The syntax for the source pattern that is passed to the constructor is as follows:
+ *
+ * <pre>
+ * SourcePattern = [ Class "." ] method [ "(" [ Parameter { ";" Parameter } ] ")" ] .
+ * Parameter = Class | "int" | "long" | "float" | "double" | "short" | "char" | "boolean" .
+ * Class = { package "." } class .
+ * </pre>
+ *
+ *
+ * Glob pattern matching (*, ?) is allowed in all parts of the source pattern. Examples for valid filters are:
+ *
+ * <ul>
+ * <li><pre>visit(Argument;BlockScope)</pre>
+ * Matches all methods named "visit", with the first parameter of type "Argument", and the second parameter of type "BlockScope".
+ * The packages of the parameter types are irrelevant.</li>
+ * <li><pre>com.oracle.graal.compiler.graph.PostOrderNodeIterator.*</pre>
+ * Matches all methods in the class "com.oracle.graal.compiler.graph.PostOrderNodeIterator".</li>
+ * <li><pre>*</pre>
+ * Matches all methods in all classes</li>
+ * <li><pre>com.oracle.graal.compiler.graph.*.visit</pre>
+ * Matches all methods named "visit" in classes in the package "com.oracle.graal.compiler.graph".</pre>
+ * </ul>
+ *
+ */
+public class MethodFilter {
+
+    private final Pattern clazz;
+    private final Pattern methodName;
+    private final Pattern[] signature;
+
+    public MethodFilter(String sourcePattern) {
+        String pattern = sourcePattern.trim();
+
+        // extract parameter part
+        int pos = pattern.indexOf('(');
+        if (pos != -1) {
+            if (pattern.charAt(pattern.length() - 1) != ')') {
+                throw new IllegalArgumentException("missing ')' at end of method filter pattern: " + pattern);
+            }
+            String[] signatureClasses = pattern.substring(pos + 1, pattern.length() - 1).split(";");
+            signature = new Pattern[signatureClasses.length];
+            for (int i = 0; i < signatureClasses.length; i++) {
+                signature[i] = createClassGlobPattern(signatureClasses[i].trim());
+            }
+            pattern = pattern.substring(0, pos);
+        } else {
+            signature = null;
+        }
+
+        // If there is at least one "." then everything before the last "." is the class name.
+        // Otherwise, the pattern contains only the method name.
+        pos = pattern.lastIndexOf('.');
+        if (pos != -1) {
+            clazz = createClassGlobPattern(pattern.substring(0, pos));
+            methodName = Pattern.compile(createGlobString(pattern.substring(pos + 1)));
+        } else {
+            clazz = null;
+            methodName = Pattern.compile(createGlobString(pattern));
+        }
+    }
+
+    private static String createGlobString(String pattern) {
+        return pattern.replace("\\", "\\\\").replace(".", "\\.").replace('?', '.').replace("*", ".*").replace("[", "\\[").replace("]", "\\]");
+    }
+
+    private static Pattern createClassGlobPattern(String pattern) {
+        if (pattern.contains(".")) {
+            return Pattern.compile(createGlobString(pattern));
+        } else {
+            return Pattern.compile("([^\\.]\\.])*" + createGlobString(pattern));
+        }
+    }
+
+    public boolean matches(RiMethod o) {
+        // check method name first, since CiUtil.toJavaName is expensive
+        if (methodName != null && !methodName.matcher(o.name()).matches()) {
+            return false;
+        }
+        if (clazz != null && !clazz.matcher(CiUtil.toJavaName(o.holder())).matches()) {
+            return false;
+        }
+        if (signature != null) {
+            RiSignature sig = o.signature();
+            if (sig.argumentCount(false) != signature.length) {
+                return false;
+            }
+            for (int i = 0; i < signature.length; i++) {
+                RiType type = sig.argumentTypeAt(i, null);
+                if (!signature[i].matcher(CiUtil.toJavaName(type)).matches()) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Mar 21 14:32:47 2012 +0100
@@ -113,5 +113,7 @@
 
     int RiMethod_vtableEntryOffset(HotSpotMethodResolved method);
 
+    long[] getDeoptedLeafGraphIds();
+
     // Checkstyle: resume
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Mar 21 14:32:47 2012 +0100
@@ -162,5 +162,8 @@
     @Override
     public native int RiMethod_vtableEntryOffset(HotSpotMethodResolved method);
 
+    @Override
+    public native long[] getDeoptedLeafGraphIds();
+
     // Checkstyle: resume
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Wed Mar 21 14:32:47 2012 +0100
@@ -218,7 +218,7 @@
 
         if (n instanceof ArrayLengthNode) {
             ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n;
-            SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.graph(), arrayLengthNode.array(), arrayLengthNode.stamp());
+            SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.graph(), arrayLengthNode.array(), arrayLengthNode.stamp(), StructuredGraph.INVALID_GRAPH_ID);
             graph.replaceFixedWithFixed(arrayLengthNode, safeReadArrayLength);
             safeReadArrayLength.lower(tool);
         } else if (n instanceof LoadFieldNode) {
@@ -229,7 +229,7 @@
             int displacement = ((HotSpotField) field.field()).offset();
             assert field.kind() != CiKind.Illegal;
             ReadNode memoryRead = graph.add(new ReadNode(field.object(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph), field.stamp()));
-            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)), RiDeoptReason.NullCheckException));
+            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID));
             graph.replaceFixedWithFixed(field, memoryRead);
         } else if (n instanceof StoreFieldNode) {
             StoreFieldNode storeField = (StoreFieldNode) n;
@@ -238,7 +238,7 @@
             }
             HotSpotField field = (HotSpotField) storeField.field();
             WriteNode memoryWrite = graph.add(new WriteNode(storeField.object(), storeField.value(), LocationNode.create(storeField.field(), storeField.field().kind(true), field.offset(), graph)));
-            memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false)), RiDeoptReason.NullCheckException));
+            memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID));
             memoryWrite.setStateAfter(storeField.stateAfter());
             graph.replaceFixedWithFixed(storeField, memoryWrite);
 
@@ -247,7 +247,7 @@
             }
         } else if (n instanceof LoadIndexedNode) {
             LoadIndexedNode loadIndexed = (LoadIndexedNode) n;
-            GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool);
+            GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool, loadIndexed.leafGraphId());
 
             CiKind elementKind = loadIndexed.elementKind();
             LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index());
@@ -256,7 +256,7 @@
             graph.replaceFixedWithFixed(loadIndexed, memoryRead);
         } else if (n instanceof StoreIndexedNode) {
             StoreIndexedNode storeIndexed = (StoreIndexedNode) n;
-            GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool);
+            GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool, storeIndexed.leafGraphId());
 
             CiKind elementKind = storeIndexed.elementKind();
             LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index());
@@ -277,7 +277,7 @@
                 } else {
                     AnchorNode anchor = graph.add(new AnchorNode());
                     graph.addBeforeFixed(storeIndexed, anchor);
-                    GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false)), RiDeoptReason.NullCheckException);
+                    GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID);
                     ReadNode arrayClass = graph.add(new ReadNode(array, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), StampFactory.objectNonNull()));
                     arrayClass.setGuard(guard);
                     graph.addBeforeFixed(storeIndexed, arrayClass);
@@ -300,7 +300,7 @@
             IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.loadKind(), load.displacement(), load.offset(), graph);
             location.setIndexScalingEnabled(false);
             ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp()));
-            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)), RiDeoptReason.NullCheckException));
+            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID));
             graph.replaceFixedWithFixed(load, memoryRead);
         } else if (n instanceof UnsafeStoreNode) {
             UnsafeStoreNode store = (UnsafeStoreNode) n;
@@ -318,7 +318,7 @@
             ReadHubNode objectClassNode = (ReadHubNode) n;
             LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph);
             ReadNode memoryRead = graph.add(new ReadNode(objectClassNode.object(), location, StampFactory.objectNonNull()));
-            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), RiDeoptReason.NullCheckException));
+            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID));
             graph.replaceFixed(objectClassNode, memoryRead);
         }
     }
@@ -327,8 +327,8 @@
         return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph);
     }
 
-    private static GuardNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) {
-        return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length())), RiDeoptReason.BoundsCheckException);
+    private static GuardNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool, long leafGraphId) {
+        return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length())), RiDeoptReason.BoundsCheckException, leafGraphId);
     }
 
     @Override
@@ -348,7 +348,7 @@
                 }
                 StructuredGraph graph = new StructuredGraph();
                 LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0));
-                SafeReadNode klassOop = safeReadHub(graph, receiver);
+                SafeReadNode klassOop = safeReadHub(graph, receiver, StructuredGraph.INVALID_GRAPH_ID);
                 FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, null, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), StampFactory.objectNonNull()));
                 ReturnNode ret = graph.add(new ReturnNode(result));
                 graph.start().setNext(klassOop);
@@ -359,7 +359,7 @@
             if (fullName.equals("getModifiers()I")) {
                 StructuredGraph graph = new StructuredGraph();
                 LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0));
-                SafeReadNode klassOop = safeRead(graph, CiKind.Object, receiver, config.klassOopOffset, StampFactory.objectNonNull());
+                SafeReadNode klassOop = safeRead(graph, CiKind.Object, receiver, config.klassOopOffset, StampFactory.objectNonNull(), StructuredGraph.INVALID_GRAPH_ID);
                 graph.start().setNext(klassOop);
                 // TODO(thomaswue): Care about primitive classes! Crashes for primitive classes at the moment (klassOop == null)
                 ReadNode result = graph.add(new ReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Int, config.klassModifierFlagsOffset, graph), StampFactory.forKind(CiKind.Int)));
@@ -378,16 +378,16 @@
         return null;
     }
 
-    private SafeReadNode safeReadHub(Graph graph, ValueNode value) {
-        return safeRead(graph, CiKind.Object, value, config.hubOffset, StampFactory.objectNonNull());
+    private SafeReadNode safeReadHub(Graph graph, ValueNode value, long leafGraphId) {
+        return safeRead(graph, CiKind.Object, value, config.hubOffset, StampFactory.objectNonNull(), leafGraphId);
     }
 
-    private SafeReadNode safeReadArrayLength(Graph graph, ValueNode value, Stamp stamp) {
-        return safeRead(graph, CiKind.Int, value, config.arrayLengthOffset, stamp);
+    private SafeReadNode safeReadArrayLength(Graph graph, ValueNode value, Stamp stamp, long leafGraphId) {
+        return safeRead(graph, CiKind.Int, value, config.arrayLengthOffset, stamp, leafGraphId);
     }
 
-    private static SafeReadNode safeRead(Graph graph, CiKind kind, ValueNode value, int offset, Stamp stamp) {
-        return graph.add(new SafeReadNode(value, LocationNode.create(LocationNode.FINAL_LOCATION, kind, offset, graph), stamp));
+    private static SafeReadNode safeRead(Graph graph, CiKind kind, ValueNode value, int offset, Stamp stamp, long leafGraphId) {
+        return graph.add(new SafeReadNode(value, LocationNode.create(LocationNode.FINAL_LOCATION, kind, offset, graph), stamp, leafGraphId));
     }
 
     public RiResolvedType getType(Class<?> clazz) {
@@ -430,6 +430,11 @@
     }
 
     @Override
+    public long[] getDeoptedLeafGraphIds() {
+        return compiler.getVMEntries().getDeoptedLeafGraphIds();
+    }
+
+    @Override
     public int encodeDeoptActionAndReason(RiDeoptAction action, RiDeoptReason reason) {
         final int actionShift = 0;
         final int reasonShift = 3;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Mar 21 14:32:47 2012 +0100
@@ -27,6 +27,7 @@
 
 import java.lang.reflect.*;
 import java.util.*;
+import java.util.concurrent.atomic.*;
 
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
@@ -87,11 +88,10 @@
 
     private BitSet canTrapBitSet;
 
-    public static final Map<RiMethod, StructuredGraph> cachedGraphs = new WeakHashMap<>();
-
     private final GraphBuilderConfiguration graphBuilderConfig;
     private final OptimisticOptimizations optimisticOpts;
 
+    private long graphId;
 
     /**
      * Node that marks the begin of block during bytecode parsing.  When a block is identified the first
@@ -115,6 +115,7 @@
     @Override
     protected void run(StructuredGraph graph) {
         method = graph.method();
+        graphId = graph.graphId();
         profilingInfo = method.profilingInfo();
         assert method.code() != null : "method must contain bytecodes: " + method;
         this.stream = new BytecodeStream(method.code());
@@ -196,10 +197,6 @@
                 n.safeDelete();
             }
         }
-
-        if (GraalOptions.CacheGraphs && !currentGraph.hasNode(DeoptimizeNode.class)) {
-            cachedGraphs.put(method, currentGraph.copy());
-        }
     }
 
     private Block unwindBlock(int bci) {
@@ -323,7 +320,7 @@
             if (riType instanceof RiResolvedType) {
                 frameState.push(CiKind.Object, append(ConstantNode.forCiConstant(((RiResolvedType) riType).getEncoding(Representation.JavaClass), runtime, currentGraph)));
             } else {
-                append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
+                append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
                 frameState.push(CiKind.Object, append(ConstantNode.forObject(null, runtime, currentGraph)));
             }
         } else if (con instanceof CiConstant) {
@@ -340,7 +337,7 @@
         ValueNode index = frameState.ipop();
         ValueNode array = frameState.apop();
         ValueNode length = append(currentGraph.add(new ArrayLengthNode(array)));
-        ValueNode v = append(currentGraph.add(new LoadIndexedNode(array, index, length, kind)));
+        ValueNode v = append(currentGraph.add(new LoadIndexedNode(array, index, length, kind, graphId)));
         frameState.push(kind.stackKind(), v);
     }
 
@@ -351,7 +348,7 @@
         ValueNode index = frameState.ipop();
         ValueNode array = frameState.apop();
         ValueNode length = append(currentGraph.add(new ArrayLengthNode(array)));
-        StoreIndexedNode result = currentGraph.add(new StoreIndexedNode(array, index, length, kind, value));
+        StoreIndexedNode result = currentGraph.add(new StoreIndexedNode(array, index, length, kind, value, graphId));
         append(result);
     }
 
@@ -582,7 +579,7 @@
 
     private void genThrow(int bci) {
         ValueNode exception = frameState.apop();
-        FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new NullCheckNode(exception, false)), RiDeoptReason.NullCheckException));
+        FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new NullCheckNode(exception, false)), RiDeoptReason.NullCheckException, graphId));
         append(node);
         append(handleException(exception, bci));
     }
@@ -674,7 +671,7 @@
             frameState.apush(checkCast);
         } else {
             ValueNode object = frameState.apop();
-            append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(object, Condition.EQ, ConstantNode.forObject(null, runtime, currentGraph))), RiDeoptReason.Unresolved)));
+            append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(object, Condition.EQ, ConstantNode.forObject(null, runtime, currentGraph))), RiDeoptReason.Unresolved, graphId)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
     }
@@ -692,7 +689,7 @@
             frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph)));
         } else {
             BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode());
-            DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved));
+            DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId));
             IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new NullCheckNode(object, true)), trueSucc, deopt, 1));
             append(ifNode);
             lastInstr = trueSucc;
@@ -706,7 +703,7 @@
             NewInstanceNode n = currentGraph.add(new NewInstanceNode((RiResolvedType) type));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
     }
@@ -747,7 +744,7 @@
             NewArrayNode n = currentGraph.add(new NewObjectArrayNode((RiResolvedType) type, length));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
 
@@ -764,7 +761,7 @@
             FixedWithNextNode n = currentGraph.add(new NewMultiArrayNode((RiResolvedType) type, dims));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
     }
@@ -778,7 +775,7 @@
             LoadFieldNode load = currentGraph.add(new LoadFieldNode(receiver, (RiResolvedField) field));
             appendOptimizedLoadField(kind, load);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
             frameState.push(kind.stackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
         }
     }
@@ -879,7 +876,7 @@
             StoreFieldNode store = currentGraph.add(new StoreFieldNode(receiver, (RiResolvedField) field, value));
             appendOptimizedStoreField(store);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
         }
     }
 
@@ -921,7 +918,7 @@
         if (initialized) {
             return appendConstant(((RiResolvedType) holder).getEncoding(representation));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
             return null;
         }
     }
@@ -982,7 +979,7 @@
     }
 
     private void genInvokeDeopt(RiMethod unresolvedTarget, boolean withReceiver) {
-        append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
+        append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
         frameState.popArguments(unresolvedTarget.signature().argumentSlots(withReceiver), unresolvedTarget.signature().argumentCount(withReceiver));
         CiKind kind = unresolvedTarget.signature().returnKind(false);
         if (kind != CiKind.Void) {
@@ -1019,7 +1016,7 @@
     private void appendInvoke(InvokeKind invokeKind, RiResolvedMethod targetMethod, ValueNode[] args) {
         CiKind resultType = targetMethod.signature().returnKind(false);
         if (GraalOptions.DeoptALot) {
-            DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(RiDeoptAction.None, RiDeoptReason.RuntimeConstraint));
+            DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(RiDeoptAction.None, RiDeoptReason.RuntimeConstraint, StructuredGraph.INVALID_GRAPH_ID));
             deoptimize.setMessage("invoke " + targetMethod.name());
             append(deoptimize);
             frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph));
@@ -1028,7 +1025,7 @@
             BeginNode exceptionEdge = handleException(null, bci());
             ValueNode result;
             if (exceptionEdge != null) {
-                InvokeWithExceptionNode invoke = currentGraph.add(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci()));
+                InvokeWithExceptionNode invoke = currentGraph.add(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci(), graphId));
                 result = append(invoke);
                 frameState.pushReturn(resultType, result);
                 Block nextBlock = currentBlock.successors.get(0);
@@ -1039,7 +1036,7 @@
                 invoke.setNext(createTarget(nextBlock, frameState));
                 invoke.setStateAfter(frameState.create(nextBlock.startBci));
             } else {
-                result = appendWithBCI(currentGraph.add(new InvokeNode(callTarget, bci())));
+                result = appendWithBCI(currentGraph.add(new InvokeNode(callTarget, bci(), graphId)));
                 frameState.pushReturn(resultType, result);
             }
         }
@@ -1108,7 +1105,7 @@
         ValueNode local = frameState.loadLocal(localIndex);
         JsrScope scope = currentBlock.jsrScope;
         int retAddress = scope.nextReturnAddress();
-        append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(local, Condition.EQ, ConstantNode.forJsr(retAddress, currentGraph))), RiDeoptReason.JavaSubroutineMismatch)));
+        append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(local, Condition.EQ, ConstantNode.forJsr(retAddress, currentGraph))), RiDeoptReason.JavaSubroutineMismatch, graphId)));
         if (!successor.jsrScope.equals(scope.pop())) {
             throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)");
         }
@@ -1194,7 +1191,7 @@
     private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) {
         assert probability >= 0 && probability <= 1;
         if (probability == 0 && optimisticOpts.removeNeverExecutedCode()) {
-            return currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.UnreachedCode));
+            return currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.UnreachedCode, graphId));
         } else {
             return createTarget(block, stateAfter);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java	Wed Mar 21 14:32:47 2012 +0100
@@ -28,6 +28,6 @@
 public interface CiLoweringTool {
     GraalRuntime getRuntime();
     Node getGuardAnchor();
-    Node createGuard(Node condition, RiDeoptReason deoptReason);
+    Node createGuard(Node condition, RiDeoptReason deoptReason, long leafGraphId);
 }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/GraalRuntime.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/GraalRuntime.java	Wed Mar 21 14:32:47 2012 +0100
@@ -39,4 +39,6 @@
     StructuredGraph intrinsicGraph(RiResolvedMethod caller, int bci, RiResolvedMethod method, List<? extends Node> parameters);
 
     CiTargetMethod compile(RiResolvedMethod method, StructuredGraph graph);
+
+    long[] getDeoptedLeafGraphIds();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -33,11 +33,14 @@
     @Data private String message;
     @Data private final RiDeoptAction action;
     @Data private final RiDeoptReason reason;
+    private final long leafGraphId;
 
-    public DeoptimizeNode(RiDeoptAction action, RiDeoptReason reason) {
+
+    public DeoptimizeNode(RiDeoptAction action, RiDeoptReason reason, long leafGraphId) {
         super(StampFactory.illegal());
         this.action = action;
         this.reason = reason;
+        this.leafGraphId = leafGraphId;
     }
 
     public void setMessage(String message) {
@@ -56,9 +59,13 @@
         return reason;
     }
 
+    public long leafGraphId() {
+        return leafGraphId;
+    }
+
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitDeoptimizeOn(null, action, reason, message);
+        gen.emitDeoptimize(action, reason, message, leafGraphId);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -32,9 +32,11 @@
 
     @Input private final NodeInputList<BooleanNode> conditions;
     @Data  private final RiDeoptReason deoptReason;
+    private final long leafGraphId;
 
-    public FixedGuardNode(BooleanNode condition, RiDeoptReason deoptReason) {
+    public FixedGuardNode(BooleanNode condition, RiDeoptReason deoptReason, long leafGraphId) {
         super(StampFactory.illegal());
+        this.leafGraphId = leafGraphId;
         this.conditions = new NodeInputList<>(this, new BooleanNode[] {condition});
         this.deoptReason = deoptReason;
     }
@@ -42,7 +44,7 @@
     @Override
     public void generate(LIRGeneratorTool gen) {
         for (BooleanNode condition : conditions()) {
-            gen.emitGuardCheck(condition, deoptReason);
+            gen.emitGuardCheck(condition, deoptReason, leafGraphId);
         }
     }
 
@@ -66,7 +68,7 @@
                     if (next != null) {
                         tool.deleteBranch(next);
                     }
-                    setNext(graph().add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, deoptReason)));
+                    setNext(graph().add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, deoptReason, leafGraphId)));
                     return;
                 }
             }
@@ -80,7 +82,7 @@
     public void lower(CiLoweringTool tool) {
         AnchorNode newAnchor = graph().add(new AnchorNode());
         for (BooleanNode b : conditions) {
-            newAnchor.addGuard((GuardNode) tool.createGuard(b, deoptReason));
+            newAnchor.addGuard((GuardNode) tool.createGuard(b, deoptReason, leafGraphId));
         }
         ((StructuredGraph) graph()).replaceFixedWithFixed(this, newAnchor);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -34,6 +34,7 @@
     @Input private BooleanNode condition;
     @Input(notDataflow = true) private FixedNode anchor;
     @Data private RiDeoptReason reason;
+    private final long leafGraphId;
 
     public FixedNode anchor() {
         return anchor;
@@ -60,16 +61,17 @@
         return reason;
     }
 
-    public GuardNode(BooleanNode condition, FixedNode anchor, RiDeoptReason reason) {
+    public GuardNode(BooleanNode condition, FixedNode anchor, RiDeoptReason reason, long leafGraphId) {
         super(StampFactory.illegal());
         this.condition = condition;
         this.anchor = anchor;
         this.reason = reason;
+        this.leafGraphId = leafGraphId;
     }
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitGuardCheck(condition(), reason());
+        gen.emitGuardCheck(condition(), reason(), leafGraphId);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Wed Mar 21 14:32:47 2012 +0100
@@ -58,4 +58,6 @@
     boolean megamorph();
 
     void setMegamorph(boolean megamorph);
+
+    long leafGraphId();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -41,6 +41,7 @@
     // megamorph should only be true when the compiler is sure that the call site is megamorph, and false when in doubt
     @Data private boolean megamorph;
     private boolean useForInlining;
+    private final long leafGraphId;
 
     /**
      * Constructs a new Invoke instruction.
@@ -50,10 +51,11 @@
      * @param target the target method being called
      * @param args the list of instructions producing arguments to the invocation, including the receiver object
      */
-    public InvokeNode(MethodCallTargetNode callTarget, int bci) {
+    public InvokeNode(MethodCallTargetNode callTarget, int bci, long leafGraphId) {
         super(callTarget.returnStamp());
         this.callTarget = callTarget;
         this.bci = bci;
+        this.leafGraphId = leafGraphId;
         this.megamorph = false;
         this.useForInlining = true;
     }
@@ -82,6 +84,11 @@
     }
 
     @Override
+    public long leafGraphId() {
+        return leafGraphId;
+    }
+
+    @Override
     public Map<Object, Object> getDebugProperties() {
         Map<Object, Object> debugProperties = super.getDebugProperties();
         if (callTarget != null && callTarget.targetMethod() != null) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -41,16 +41,18 @@
     // megamorph should only be true when the compiler is sure that the call site is megamorph, and false when in doubt
     @Data private boolean megamorph;
     private boolean useForInlining;
+    private final long leafGraphId;
 
     /**
      * @param kind
      * @param blockSuccessors
      * @param branchProbability
      */
-    public InvokeWithExceptionNode(MethodCallTargetNode callTarget, BeginNode exceptionEdge, int bci) {
+    public InvokeWithExceptionNode(MethodCallTargetNode callTarget, BeginNode exceptionEdge, int bci, long leafGraphId) {
         super(callTarget.returnStamp(), new BeginNode[]{null, exceptionEdge}, new double[]{1.0, 0.0});
         this.bci = bci;
         this.callTarget = callTarget;
+        this.leafGraphId = leafGraphId;
         this.megamorph = true;
         this.useForInlining = true;
     }
@@ -96,6 +98,11 @@
     }
 
     @Override
+    public long leafGraphId() {
+        return leafGraphId;
+    }
+
+    @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Long) {
             return super.toString(Verbosity.Short) + "(bci=" + bci() + ")";
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed Mar 21 14:32:47 2012 +0100
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes;
 
 import java.util.*;
+import java.util.concurrent.atomic.*;
 
 import com.oracle.max.cri.ri.*;
 import com.oracle.graal.graph.*;
@@ -36,8 +37,19 @@
  * This node is the start of the control flow of the graph.
  */
 public class StructuredGraph extends Graph {
+
+    public static final long INVALID_GRAPH_ID = -1;
+    private static final AtomicLong uniqueGraphIds = new AtomicLong();
     private final BeginNode start;
     private final RiResolvedMethod method;
+    private final long graphId;
+
+    /**
+     * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node.
+     */
+    public StructuredGraph() {
+        this(null, null);
+    }
 
     /**
      * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node.
@@ -50,13 +62,7 @@
         super(name);
         this.start = add(new BeginNode());
         this.method = method;
-    }
-
-    /**
-     * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node.
-     */
-    public StructuredGraph() {
-        this((String) null);
+        this.graphId = uniqueGraphIds.incrementAndGet();
     }
 
     public StructuredGraph(RiResolvedMethod method) {
@@ -71,6 +77,10 @@
         return method;
     }
 
+    public long graphId() {
+        return graphId;
+    }
+
     @Override
     public StructuredGraph copy() {
         return copy(name);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -57,7 +57,7 @@
     public void expand(BoxingMethodPool pool) {
         RiResolvedMethod boxingMethod = pool.getBoxingMethod(sourceKind);
         MethodCallTargetNode callTarget = graph().add(new MethodCallTargetNode(InvokeKind.Static, boxingMethod, new ValueNode[]{source}, boxingMethod.signature().returnType(boxingMethod.holder())));
-        InvokeNode invokeNode = graph().add(new InvokeNode(callTarget, bci));
+        InvokeNode invokeNode = graph().add(new InvokeNode(callTarget, bci, -1));
         invokeNode.setProbability(this.probability());
         invokeNode.setStateAfter(stateAfter());
         ((StructuredGraph) graph()).replaceFixedWithFixed(this, invokeNode);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeAccessNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeAccessNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -30,11 +30,13 @@
 
     @Input private ValueNode object;
     @Input private LocationNode location;
+    private final long leafGraphId;
 
-    public SafeAccessNode(ValueNode object, LocationNode location, Stamp stamp) {
+    public SafeAccessNode(ValueNode object, LocationNode location, Stamp stamp, long leafGraphId) {
         super(stamp);
         this.object = object;
         this.location = location;
+        this.leafGraphId = leafGraphId;
     }
 
     public ValueNode object() {
@@ -44,4 +46,8 @@
     public LocationNode location() {
         return location;
     }
+
+    public long leafGraphId() {
+        return leafGraphId;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -32,15 +32,15 @@
 
 public class SafeReadNode extends SafeAccessNode implements Lowerable {
 
-    public SafeReadNode(ValueNode object, LocationNode location, Stamp stamp) {
-        super(object, location, stamp);
+    public SafeReadNode(ValueNode object, LocationNode location, Stamp stamp, long leafGraphId) {
+        super(object, location, stamp, leafGraphId);
         assert object != null && location != null;
     }
 
     @Override
     public void lower(CiLoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) graph();
-        GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException);
+        GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID);
         ReadNode read = graph.add(new ReadNode(object(), location(), stamp()));
         read.setGuard(guard);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -35,8 +35,8 @@
 
     @Input private ValueNode value;
 
-    public SafeWriteNode(ValueNode object, ValueNode value, LocationNode location) {
-        super(object, location, StampFactory.forKind(CiKind.Void));
+    public SafeWriteNode(ValueNode object, ValueNode value, LocationNode location, long leafGraphId) {
+        super(object, location, StampFactory.forKind(CiKind.Void), leafGraphId);
         this.value = value;
     }
 
@@ -47,7 +47,7 @@
     @Override
     public void lower(CiLoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) graph();
-        GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException);
+        GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID);
         WriteNode write = graph.add(new WriteNode(object(), value(), location()));
         write.setGuard(guard);
         graph.replaceFixedWithFixed(this, write);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -46,6 +46,7 @@
     }
 
     private final CiKind elementType;
+    private final long leafGraphId;
 
     /**
      * Create an new AccessIndexedNode.
@@ -55,11 +56,12 @@
      * @param length the instruction producing the length
      * @param elementKind the type of the elements of the array
      */
-    protected AccessIndexedNode(Stamp stamp, ValueNode array, ValueNode index, ValueNode length, CiKind elementKind) {
+    protected AccessIndexedNode(Stamp stamp, ValueNode array, ValueNode index, ValueNode length, CiKind elementKind, long leafGraphId) {
         super(stamp, array);
         this.index = index;
         this.length = length;
         this.elementType = elementKind;
+        this.leafGraphId = leafGraphId;
     }
 
     /**
@@ -70,6 +72,10 @@
         return elementType;
     }
 
+    public long leafGraphId() {
+        return leafGraphId;
+    }
+
     @Override
     public void typeFeedback(TypeFeedbackTool tool) {
         tool.addScalar(index()).constantBound(Condition.GE, CiConstant.INT_0);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -41,8 +41,8 @@
      * @param length the instruction producing the length
      * @param elementKind the element type
      */
-    public LoadIndexedNode(ValueNode array, ValueNode index, ValueNode length, CiKind elementKind) {
-        super(createStamp(array, elementKind), array, index, length, elementKind);
+    public LoadIndexedNode(ValueNode array, ValueNode index, ValueNode length, CiKind elementKind, long leafGraphId) {
+        super(createStamp(array, elementKind), array, index, length, elementKind, leafGraphId);
     }
 
     private static Stamp createStamp(ValueNode array, CiKind kind) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Wed Mar 21 14:32:47 2012 +0100
@@ -47,8 +47,8 @@
      * @param elementKind the element type
      * @param value the value to store into the array
      */
-    public StoreIndexedNode(ValueNode array, ValueNode index, ValueNode length, CiKind elementKind, ValueNode value) {
-        super(StampFactory.illegal(), array, index, length, elementKind);
+    public StoreIndexedNode(ValueNode array, ValueNode index, ValueNode length, CiKind elementKind, ValueNode value, long leafGraphId) {
+        super(StampFactory.illegal(), array, index, length, elementKind, leafGraphId);
         this.value = value;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Mar 21 14:32:47 2012 +0100
@@ -79,12 +79,13 @@
 
     public abstract CiValue emitConvert(ConvertNode.Op opcode, CiValue inputVal);
     public abstract void emitMembar(int barriers);
-    public abstract void emitDeoptimizeOn(Condition of, RiDeoptAction action, RiDeoptReason reason, Object deoptInfo);
+    public abstract void emitDeoptimizeOn(Condition cond, RiDeoptAction action, RiDeoptReason reason, Object deoptInfo);
+    public abstract void emitDeoptimize(RiDeoptAction action, RiDeoptReason reason, Object deoptInfo, long leafGraphId);
     public abstract CiValue emitCallToRuntime(CiRuntimeCall runtimeCall, boolean canTrap, CiValue... args);
 
     public abstract void emitIf(IfNode i);
     public abstract void emitConditional(ConditionalNode i);
-    public abstract void emitGuardCheck(BooleanNode comp, RiDeoptReason deoptReason);
+    public abstract void emitGuardCheck(BooleanNode comp, RiDeoptReason deoptReason, long leafGraphId);
 
     public abstract void emitLookupSwitch(LookupSwitchNode i);
     public abstract void emitTableSwitch(TableSwitchNode i);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java	Wed Mar 21 14:32:47 2012 +0100
@@ -114,8 +114,17 @@
         }
 
         @Override
-        public boolean notExactType(RiResolvedType type) {
-            return false;
+        public boolean notExactType(final RiResolvedType type) {
+            return store.prove(Info.class, new BooleanPredicate<Info>() {
+                @Override
+                public boolean evaluate(Info element) {
+                    if (element instanceof ObjectTypeExact) {
+                        return ((ObjectTypeExact) element).type != type;
+                    } else {
+                        return (element instanceof Equals) && ((Equals) element).constant.isNull();
+                    }
+                }
+            });
         }
 
         @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ScalarTypeFeedbackStore.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ScalarTypeFeedbackStore.java	Wed Mar 21 14:32:47 2012 +0100
@@ -24,10 +24,10 @@
 
 import java.util.*;
 
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.max.cri.ci.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
 
 public class ScalarTypeFeedbackStore extends TypeFeedbackStore<ScalarTypeFeedbackStore> implements ScalarTypeFeedbackTool, CloneableTypeFeedback {
 
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiCodePos.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiCodePos.java	Wed Mar 21 14:32:47 2012 +0100
@@ -32,10 +32,8 @@
  * can be used by the runtime system to reconstruct a source-level stack trace
  * for exceptions and to create {@linkplain CiFrame frames} for deoptimization.
  */
-public class CiCodePos implements Serializable {
-    /**
-     * 
-     */
+public abstract class CiCodePos implements Serializable {
+
     private static final long serialVersionUID = 8633885274526033515L;
 
     /**
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiFrame.java	Wed Mar 21 13:57:30 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiFrame.java	Wed Mar 21 14:32:47 2012 +0100
@@ -65,6 +65,8 @@
      */
     public final int numLocks;
 
+    public final long leafGraphId;
+
     public final boolean rethrowException;
 
     public final boolean duringCall;
@@ -81,15 +83,16 @@
      * @param numStack the depth of the stack
      * @param numLocks the number of locked objects
      */
-    public CiFrame(CiFrame caller, RiResolvedMethod method, int bci, boolean rethrowException, boolean duringCall, CiValue[] values, int numLocals, int numStack, int numLocks) {
+    public CiFrame(CiFrame caller, RiResolvedMethod method, int bci, boolean rethrowException, boolean duringCall, CiValue[] values, int numLocals, int numStack, int numLocks, long leafGraphId) {
         super(caller, method, bci);
         assert values != null;
         this.rethrowException = rethrowException;
+        this.duringCall = duringCall;
         this.values = values;
-        this.numLocks = numLocks;
         this.numLocals = numLocals;
         this.numStack = numStack;
-        this.duringCall = duringCall;
+        this.numLocks = numLocks;
+        this.leafGraphId = leafGraphId;
         assert !rethrowException || numStack == 1 : "must have exception on top of the stack";
     }
 
--- a/src/share/vm/c1/c1_IR.cpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/c1/c1_IR.cpp	Wed Mar 21 14:32:47 2012 +0100
@@ -210,7 +210,7 @@
 
 void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset) {
   // record the safepoint before recording the debug info for enclosing scopes
-  recorder->add_safepoint(pc_offset, _oop_map->deep_copy());
+  recorder->add_safepoint(pc_offset, -1, _oop_map->deep_copy());
   _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/, _is_method_handle_invoke);
   recorder->end_safepoint(pc_offset);
 }
--- a/src/share/vm/code/debugInfoRec.cpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/code/debugInfoRec.cpp	Wed Mar 21 14:32:47 2012 +0100
@@ -127,14 +127,14 @@
   _oopmaps->add_gc_map(pc_offset, map);
 }
 
-void DebugInformationRecorder::add_safepoint(int pc_offset, OopMap* map) {
+void DebugInformationRecorder::add_safepoint(int pc_offset, jlong leaf_graph_id, OopMap* map) {
   assert(!_oop_recorder->is_complete(), "not frozen yet");
   // Store the new safepoint
 
   // Add the oop map
   add_oopmap(pc_offset, map);
 
-  add_new_pc_offset(pc_offset);
+  add_new_pc_offset(pc_offset, leaf_graph_id);
 
   assert(_recording_state == rs_null, "nesting of recording calls");
   debug_only(_recording_state = rs_safepoint);
@@ -150,7 +150,7 @@
   debug_only(_recording_state = rs_non_safepoint);
 }
 
-void DebugInformationRecorder::add_new_pc_offset(int pc_offset) {
+void DebugInformationRecorder::add_new_pc_offset(int pc_offset, jlong leaf_graph_id) {
   assert(_pcs_length == 0 || last_pc()->pc_offset() < pc_offset,
          "must specify a new, larger pc offset");
 
@@ -168,7 +168,7 @@
   assert(_pcs_size > _pcs_length, "There must be room for after expanding");
 
   _pcs[_pcs_length++] = PcDesc(pc_offset, DebugInformationRecorder::serialized_null,
-                               DebugInformationRecorder::serialized_null);
+                               DebugInformationRecorder::serialized_null, leaf_graph_id);
 }
 
 
--- a/src/share/vm/code/debugInfoRec.hpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/code/debugInfoRec.hpp	Wed Mar 21 14:32:47 2012 +0100
@@ -82,7 +82,7 @@
   void add_oopmap(int pc_offset, OopMap* map);
 
   // adds a jvm mapping at pc-offset, for a safepoint only
-  void add_safepoint(int pc_offset, OopMap* map);
+  void add_safepoint(int pc_offset, jlong leaf_graph_id, OopMap* map);
 
   // adds a jvm mapping at pc-offset, for a non-safepoint (profile point)
   void add_non_safepoint(int pc_offset);
@@ -188,7 +188,7 @@
     guarantee(_pcs_length > 1, "a safepoint must be declared already");
     return &_pcs[_pcs_length-2];
   }
-  void add_new_pc_offset(int pc_offset);
+  void add_new_pc_offset(int pc_offset, jlong leaf_graph_id = -1);
   void end_scopes(int pc_offset, bool is_safepoint);
 
   int  serialize_monitor_values(GrowableArray<MonitorValue*>* monitors);
--- a/src/share/vm/code/nmethod.hpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/code/nmethod.hpp	Wed Mar 21 14:32:47 2012 +0100
@@ -596,7 +596,7 @@
 
   // (thomaswue) When using graal, the address might be off by 5 (because this is the size of the call instruction.
   // (thomaswue) TODO: Replace this by a more general mechanism.
-  bool is_deopt_entry   (address pc) { return pc == deopt_handler_begin() IS_GRAAL( || pc == deopt_handler_begin() + 5); }
+  bool is_deopt_entry   (address pc) { return pc == deopt_handler_begin() GRAAL_ONLY( || pc == deopt_handler_begin() + 5); }
   bool is_deopt_mh_entry(address pc) { return pc == deopt_mh_handler_begin(); }
   // Accessor/mutator for the original pc of a frame before a frame was deopted.
   address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
--- a/src/share/vm/code/pcDesc.cpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/code/pcDesc.cpp	Wed Mar 21 14:32:47 2012 +0100
@@ -29,11 +29,12 @@
 #include "code/scopeDesc.hpp"
 #include "memory/resourceArea.hpp"
 
-PcDesc::PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset) {
+PcDesc::PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset, jlong leaf_graph_id) {
   _pc_offset           = pc_offset;
   _scope_decode_offset = scope_decode_offset;
   _obj_decode_offset   = obj_decode_offset;
   _flags               = 0;
+  GRAAL_ONLY(_leaf_graph_id = leaf_graph_id);
 }
 
 address PcDesc::real_pc(const nmethod* code) const {
@@ -43,7 +44,11 @@
 void PcDesc::print(nmethod* code) {
 #ifndef PRODUCT
   ResourceMark rm;
+#ifdef GRAAL
+  tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x leaf_graph_id=%d):", real_pc(code), pc_offset(), _flags, leaf_graph_id());
+#else
   tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x):", real_pc(code), pc_offset(), _flags);
+#endif
 
   if (scope_decode_offset() == DebugInformationRecorder::serialized_null) {
     return;
--- a/src/share/vm/code/pcDesc.hpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/code/pcDesc.hpp	Wed Mar 21 14:32:47 2012 +0100
@@ -38,6 +38,7 @@
   int _pc_offset;           // offset from start of nmethod
   int _scope_decode_offset; // offset for scope in nmethod
   int _obj_decode_offset;
+  GRAAL_ONLY(jlong _leaf_graph_id;)
 
   enum {
     PCDESC_reexecute               = 1 << 0,
@@ -56,6 +57,7 @@
   int pc_offset() const           { return _pc_offset;   }
   int scope_decode_offset() const { return _scope_decode_offset; }
   int obj_decode_offset() const   { return _obj_decode_offset; }
+  jlong leaf_graph_id() const     { return GRAAL_ONLY(_leaf_graph_id) NOT_GRAAL(-1); }
 
   void set_pc_offset(int x)           { _pc_offset           = x; }
   void set_scope_decode_offset(int x) { _scope_decode_offset = x; }
@@ -63,7 +65,7 @@
 
   // Constructor (only used for static in nmethod.cpp)
   // Also used by ScopeDesc::sender()]
-  PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset);
+  PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset, jlong leaf_graph_id);
 
   enum {
     // upper and lower exclusive limits real offsets:
@@ -81,7 +83,9 @@
   bool is_same_info(const PcDesc* pd) {
     return _scope_decode_offset == pd->_scope_decode_offset &&
       _obj_decode_offset == pd->_obj_decode_offset &&
-      _flags == pd->_flags;
+      _flags == pd->_flags
+      GRAAL_ONLY(&& _leaf_graph_id == pd->_leaf_graph_id)
+      ;
   }
 
   bool     is_method_handle_invoke()       const { return (_flags & PCDESC_is_method_handle_invoke) != 0;     }
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Mar 21 14:32:47 2012 +0100
@@ -440,19 +440,16 @@
   }
 }
 
-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, objects);
-  }
-  oop frame = NULL;
-  if (code_pos->klass()->klass_part()->name() == vmSymbols::com_oracle_max_cri_ci_CiFrame()) {
-    frame = code_pos;
+void CodeInstaller::record_scope(jint pc_offset, oop frame, GrowableArray<ScopeValue*>* objects) {
+  assert(frame->klass() == CiFrame::klass(), "CiFrame expected");
+  oop caller_frame = CiCodePos::caller(frame);
+  if (caller_frame != NULL) {
+    record_scope(pc_offset, caller_frame, objects);
   }
 
-  oop hotspot_method = CiCodePos::method(code_pos);
+  oop hotspot_method = CiCodePos::method(frame);
   methodOop method = getMethodFromHotSpotMethod(hotspot_method);
-  jint bci = CiCodePos::bci(code_pos);
+  jint bci = CiCodePos::bci(frame);
   bool reexecute;
   if (bci == -1) {
      reexecute = false;
@@ -468,64 +465,60 @@
     tty->print_cr("Recording scope pc_offset=%d bci=%d frame=%d", pc_offset, bci, frame);
   }
 
-  if (frame != NULL) {
-    jint local_count = CiFrame::numLocals(frame);
-    jint expression_count = CiFrame::numStack(frame);
-    jint monitor_count = CiFrame::numLocks(frame);
-    arrayOop values = (arrayOop) CiFrame::values(frame);
+  jint local_count = CiFrame::numLocals(frame);
+  jint expression_count = CiFrame::numStack(frame);
+  jint monitor_count = CiFrame::numLocks(frame);
+  arrayOop values = (arrayOop) CiFrame::values(frame);
 
-    assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length");
+  assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length");
 
-    GrowableArray<ScopeValue*>* locals = new GrowableArray<ScopeValue*> ();
-    GrowableArray<ScopeValue*>* expressions = new GrowableArray<ScopeValue*> ();
-    GrowableArray<MonitorValue*>* monitors = new GrowableArray<MonitorValue*> ();
+  GrowableArray<ScopeValue*>* locals = new GrowableArray<ScopeValue*> ();
+  GrowableArray<ScopeValue*>* expressions = new GrowableArray<ScopeValue*> ();
+  GrowableArray<MonitorValue*>* monitors = new GrowableArray<MonitorValue*> ();
 
-    if (TraceGraal >= 2) {
-      tty->print_cr("Scope at bci %d with %d values", bci, values->length());
-      tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count);
-    }
+  if (TraceGraal >= 2) {
+    tty->print_cr("Scope at bci %d with %d values", bci, values->length());
+    tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count);
+  }
 
-    for (jint i = 0; i < values->length(); i++) {
-      ScopeValue* second = NULL;
-      oop value = ((oop*) values->base(T_OBJECT))[i];
+  for (jint i = 0; i < values->length(); i++) {
+    ScopeValue* second = NULL;
+    oop value = ((oop*) values->base(T_OBJECT))[i];
 
-      if (i < local_count) {
-        ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second);
-        if (second != NULL) {
-          locals->append(second);
-        }
-        locals->append(first);
-      } else if (i < local_count + expression_count) {
-        ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second);
-        if (second != NULL) {
-          expressions->append(second);
-        }
-        expressions->append(first);
-      } else {
-        monitors->append(get_monitor_value(value, _total_frame_size, objects));
+    if (i < local_count) {
+      ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second);
+      if (second != NULL) {
+        locals->append(second);
       }
+      locals->append(first);
+    } else if (i < local_count + expression_count) {
+      ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second);
       if (second != NULL) {
-        i++;
-        assert(i < values->length(), "double-slot value not followed by CiValue.IllegalValue");
-        assert(((oop*) values->base(T_OBJECT))[i] == CiValue::IllegalValue(), "double-slot value not followed by CiValue.IllegalValue");
+        expressions->append(second);
       }
+      expressions->append(first);
+    } else {
+      monitors->append(get_monitor_value(value, _total_frame_size, objects));
     }
-
-    _debug_recorder->dump_object_pool(objects);
+    if (second != NULL) {
+      i++;
+      assert(i < values->length(), "double-slot value not followed by CiValue.IllegalValue");
+      assert(((oop*) values->base(T_OBJECT))[i] == CiValue::IllegalValue(), "double-slot value not followed by CiValue.IllegalValue");
+    }
+  }
 
-    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);
+  _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);
 
-    bool throw_exception = false;
-    if (CiFrame::rethrowException(frame)) {
-      throw_exception = true;
-    }
+  bool throw_exception = false;
+  if (CiFrame::rethrowException(frame)) {
+    throw_exception = true;
+  }
 
-    _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token);
-  } else {
-    _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, false, false, false, NULL, NULL, NULL);
-  }
+  _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token);
 }
 
 void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) {
@@ -534,7 +527,7 @@
 
   // address instruction = _instructions->start() + pc_offset;
   // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start();
-  _debug_recorder->add_safepoint(pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info));
+  _debug_recorder->add_safepoint(pc_offset, -1, create_oop_map(_total_frame_size, _parameter_count, debug_info));
 
   oop code_pos = CiDebugInfo::codePos(debug_info);
   record_scope(pc_offset, code_pos, new GrowableArray<ScopeValue*>());
@@ -648,9 +641,9 @@
   }
 
   if (debug_info != NULL) {
-    _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info));
-    oop code_pos = CiDebugInfo::codePos(debug_info);
-    record_scope(next_pc_offset, code_pos, new GrowableArray<ScopeValue*>());
+    oop frame = CiDebugInfo::codePos(debug_info);
+    _debug_recorder->add_safepoint(next_pc_offset, CiFrame::leafGraphId(frame), create_oop_map(_total_frame_size, _parameter_count, debug_info));
+    record_scope(next_pc_offset, frame, new GrowableArray<ScopeValue*>());
   }
 
   if (runtime_call != NULL) {
--- a/src/share/vm/graal/graalCompiler.cpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/graal/graalCompiler.cpp	Wed Mar 21 14:32:47 2012 +0100
@@ -47,6 +47,8 @@
   JavaThread* THREAD = JavaThread::current();
   TRACE_graal_1("GraalCompiler::initialize");
 
+  _deopted_leaf_graph_count = 0;
+
   initialize_buffer_blob();
   Runtime1::initialize(THREAD->get_buffer_blob());
 
@@ -91,6 +93,47 @@
   }
 }
 
+void GraalCompiler::deopt_leaf_graph(jlong leaf_graph_id) {
+  assert(leaf_graph_id != -1, "unexpected leaf graph id");
+
+  if (_deopted_leaf_graph_count < LEAF_GRAPH_ARRAY_SIZE) {
+    MutexLockerEx y(GraalDeoptLeafGraphIds_lock, Mutex::_no_safepoint_check_flag);
+    if (_deopted_leaf_graph_count < LEAF_GRAPH_ARRAY_SIZE) {
+      _deopted_leaf_graphs[_deopted_leaf_graph_count++] = leaf_graph_id;
+    }
+  }
+}
+
+oop GraalCompiler::dump_deopted_leaf_graphs(TRAPS) {
+  if (_deopted_leaf_graph_count == 0) {
+    return NULL;
+  }
+  jlong* elements;
+  int length;
+  {
+    MutexLockerEx y(GraalDeoptLeafGraphIds_lock, Mutex::_no_safepoint_check_flag);
+    if (_deopted_leaf_graph_count == 0) {
+      return NULL;
+    }
+    if (_deopted_leaf_graph_count == LEAF_GRAPH_ARRAY_SIZE) {
+      length = 0;
+    } else {
+      length = _deopted_leaf_graph_count;
+    }
+    elements = new jlong[length];
+    for (int i = 0; i < length; i++) {
+      elements[i] = _deopted_leaf_graphs[i];
+    }
+    _deopted_leaf_graph_count = 0;
+  }
+  typeArrayOop array = oopFactory::new_longArray(length, CHECK_NULL);
+  for (int i = 0; i < length; i++) {
+    array->long_at_put(i, elements[i]);
+  }
+  delete elements;
+  return array;
+}
+
 void GraalCompiler::initialize_buffer_blob() {
 
   JavaThread* THREAD = JavaThread::current();
--- a/src/share/vm/graal/graalCompiler.hpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/graal/graalCompiler.hpp	Wed Mar 21 14:32:47 2012 +0100
@@ -23,13 +23,18 @@
 
 #include "compiler/abstractCompiler.hpp"
 
+#define LEAF_GRAPH_ARRAY_SIZE (8192)
+
 class GraalCompiler : public AbstractCompiler {
 
 private:
 
   bool                  _initialized;
 
-  static GraalCompiler*   _instance;
+  static GraalCompiler* _instance;
+
+  jlong                 _deopted_leaf_graphs[LEAF_GRAPH_ARRAY_SIZE];
+  int                   _deopted_leaf_graph_count;
 
 public:
 
@@ -56,6 +61,9 @@
 
   void compile_method(methodHandle target, int entry_bci, jboolean blocking);
 
+  void deopt_leaf_graph(jlong leaf_graph_id);
+  oop dump_deopted_leaf_graphs(TRAPS);
+
   // Print compilation timers and statistics
   virtual void print_timers();
   
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Mar 21 14:32:47 2012 +0100
@@ -967,6 +967,21 @@
   return vtable_entry_offset;
 }
 
+// public native long[] getDeoptedLeafGraphIds();
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getDeoptedLeafGraphIds(JNIEnv *, jobject) {
+  TRACE_graal_3("CompilerToVM::getDeoptedLeafGraphIds");
+
+  VM_ENTRY_MARK;
+
+  // the contract for this method is as follows:
+  // returning null: no deopted leaf graphs
+  // returning array (size > 0): the ids of the deopted leaf graphs
+  // returning array (size == 0): there was an overflow, the compiler needs to clear its cache completely
+
+  oop array = GraalCompiler::instance()->dump_deopted_leaf_graphs(CHECK_NULL);
+  return JNIHandles::make_local(array);
+}
+
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_##f))
@@ -1030,6 +1045,7 @@
   {CC"disassembleJava",                   CC"("RESOLVED_METHOD")"STRING,                        FN_PTR(disassembleJava)},
   {CC"executeCompiledMethod",             CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT,    FN_PTR(executeCompiledMethod)},
   {CC"RiMethod_vtableEntryOffset",        CC"("RESOLVED_METHOD")I",                             FN_PTR(RiMethod_vtableEntryOffset)},
+  {CC"getDeoptedLeafGraphIds",            CC"()[J",                                             FN_PTR(getDeoptedLeafGraphIds)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalJavaAccess.hpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Wed Mar 21 14:32:47 2012 +0100
@@ -163,6 +163,7 @@
     int_field(CiFrame, numLocals)                                                       \
     int_field(CiFrame, numStack)                                                        \
     int_field(CiFrame, numLocks)                                                        \
+    long_field(CiFrame, leafGraphId)                                                    \
     boolean_field(CiFrame, rethrowException)                                            \
     boolean_field(CiFrame, duringCall)                                                  \
   end_class                                                                             \
--- a/src/share/vm/opto/output.cpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/opto/output.cpp	Wed Mar 21 14:32:47 2012 +0100
@@ -815,7 +815,7 @@
   // Add the safepoint in the DebugInfoRecorder
   if( !mach->is_MachCall() ) {
     mcall = NULL;
-    debug_info()->add_safepoint(safepoint_pc_offset, sfn->_oop_map);
+    debug_info()->add_safepoint(safepoint_pc_offset, -1, sfn->_oop_map);
   } else {
     mcall = mach->as_MachCall();
 
@@ -833,7 +833,7 @@
       return_oop = true;
     }
     safepoint_pc_offset += mcall->ret_addr_offset();
-    debug_info()->add_safepoint(safepoint_pc_offset, mcall->_oop_map);
+    debug_info()->add_safepoint(safepoint_pc_offset, -1, mcall->_oop_map);
   }
 
   // Loop over the JVMState list to add scope information
--- a/src/share/vm/runtime/deoptimization.cpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/runtime/deoptimization.cpp	Wed Mar 21 14:32:47 2012 +0100
@@ -86,6 +86,11 @@
 #endif
 #endif
 
+#ifdef GRAAL
+#include "graal/graalCompiler.hpp"
+#endif
+
+
 bool DeoptimizationMarker::_is_active = false;
 
 Deoptimization::UnrollBlock::UnrollBlock(int  size_of_deoptimized_frame,
@@ -201,6 +206,19 @@
   // Create a growable array of VFrames where each VFrame represents an inlined
   // Java frame.  This storage is allocated with the usual system arena.
   assert(deoptee.is_compiled_frame(), "Wrong frame type");
+
+#ifdef GRAAL
+  PcDesc* pc_desc = ((nmethod*) deoptee.cb())->pc_desc_at(deoptee.pc());
+  int decode_offset;
+  if (pc_desc != NULL && pc_desc->leaf_graph_id() != -1) {
+    GraalCompiler* compiler = (GraalCompiler*) ((nmethod*) deoptee.cb())->compiler();
+    if (PrintDeoptimizationDetails) {
+      tty->print_cr("leaf graph id: %d", pc_desc->leaf_graph_id());
+    }
+    compiler->deopt_leaf_graph(pc_desc->leaf_graph_id());
+  }
+#endif
+
   GrowableArray<compiledVFrame*>* chunk = new GrowableArray<compiledVFrame*>(10);
   vframe* vf = vframe::new_vframe(&deoptee, &map, thread);
   while (!vf->is_top()) {
@@ -1706,7 +1724,7 @@
   bool ignore_maybe_prior_trap;
   bool ignore_maybe_prior_recompile;
   // Graal uses the total counts to determine if deoptimizations are happening too frequently -> do not adjust total counts
-  bool update_total_counts = IS_GRAAL(false) NOT_GRAAL(true);
+  bool update_total_counts = GRAAL_ONLY(false) NOT_GRAAL(true);
   query_update_method_data(trap_mdo, trap_bci,
                            (DeoptReason)reason,
                            update_total_counts,
--- a/src/share/vm/runtime/mutexLocker.cpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/runtime/mutexLocker.cpp	Wed Mar 21 14:32:47 2012 +0100
@@ -141,6 +141,10 @@
 Mutex*   JfrBuffer_lock               = NULL;
 Mutex*   JfrStream_lock               = NULL;
 
+#ifdef GRAAL
+Mutex*   GraalDeoptLeafGraphIds_lock  = NULL;
+#endif // GRAAL
+
 #define MAX_NUM_MUTEX 128
 static Monitor * _mutex_array[MAX_NUM_MUTEX];
 static int _num_mutex;
@@ -285,6 +289,10 @@
   def(JfrMsg_lock                  , Monitor, nonleaf+2,   true);
   def(JfrBuffer_lock               , Mutex,   nonleaf+3,   true);
   def(JfrStream_lock               , Mutex,   nonleaf+4,   true);
+
+#ifdef GRAAL
+  def(GraalDeoptLeafGraphIds_lock  , Mutex,   special,   true);
+#endif // GRAAL
 }
 
 GCMutexLocker::GCMutexLocker(Monitor * mutex) {
--- a/src/share/vm/runtime/mutexLocker.hpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/runtime/mutexLocker.hpp	Wed Mar 21 14:32:47 2012 +0100
@@ -143,6 +143,10 @@
 extern Mutex*   JfrBuffer_lock;                  // protects JFR buffer operations
 extern Mutex*   JfrStream_lock;                  // protects JFR stream access
 
+#ifdef GRAAL
+extern Mutex*   GraalDeoptLeafGraphIds_lock;     // protects access to the global array of deopt'ed leaf graphs
+#endif // GRAAL
+
 // A MutexLocker provides mutual exclusion with respect to a given mutex
 // for the scope which contains the locker.  The lock is an OS lock, not
 // an object lock, and the two do not interoperate.  Do not use Mutex-based
--- a/src/share/vm/shark/sharkCacheDecache.cpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/shark/sharkCacheDecache.cpp	Wed Mar 21 14:32:47 2012 +0100
@@ -40,7 +40,7 @@
   _oopmap = new OopMap(
     oopmap_slot_munge(stack()->oopmap_frame_size()),
     oopmap_slot_munge(arg_size()));
-  debug_info()->add_safepoint(pc_offset(), oopmap());
+  debug_info()->add_safepoint(pc_offset(), -1, oopmap());
 }
 
 void SharkDecacher::start_stack(int stack_depth) {
--- a/src/share/vm/utilities/macros.hpp	Wed Mar 21 13:57:30 2012 +0100
+++ b/src/share/vm/utilities/macros.hpp	Wed Mar 21 14:32:47 2012 +0100
@@ -75,10 +75,10 @@
 #endif // COMPILER2
 
 #ifdef GRAAL
-#define IS_GRAAL(code) code
+#define GRAAL_ONLY(code...) code
 #define NOT_GRAAL(code)
 #else
-#define IS_GRAAL(code)
+#define GRAAL_ONLY(code...)
 #define NOT_GRAAL(code) code
 #endif