changeset 5350:de571c017f61

Merge
author Gilles Duboscq <duboscq@ssw.jku.at>
date Thu, 03 May 2012 11:05:46 +0200
parents 00803ae428d2 (diff) 077ec9468516 (current diff)
children 5698355398e3
files
diffstat 73 files changed, 1027 insertions(+), 762 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Thu May 03 11:05:46 2012 +0200
@@ -207,6 +207,15 @@
     public static boolean OptSafepointElimination            = true;
 
     /**
+     * Insert a counter in the method prologue to track the most frequently called methods that were compiled by Graal.
+     */
+    public static boolean MethodEntryCounters               = false;
+    /**
+     * Number of caller program counters to distinguish when counting methods.
+     */
+    public static int     MethodEntryCountersCallers        = 20;
+
+    /**
      * Flag to turn on SSA-based register allocation, which is currently under development.
      */
     public static boolean AllocSSA                           = false;
@@ -216,6 +225,26 @@
      */
     public static boolean PrintFlags                           = false;
 
+    /**
+     * Counts the various paths taken through a compiled checkcast.
+     */
+    public static boolean CheckcastCounters = false;
+
+    /**
+     * If the probability that a checkcast will hit one the profiled types (up to {@link #CheckcastMaxHints})
+     * is below this value, the checkcast will be compiled without hints.
+     */
+    public static double CheckcastMinHintHitProbability = 0.5;
+
+    /**
+     * The maximum number of hint types that will be used when compiling a checkcast for which
+     * profiling information is available. Note that {@link #CheckcastMinHintHitProbability}
+     * also influences whether hints are used.
+     */
+    public static int CheckcastMaxHints = 2;
+
+    public static int InstanceOfMaxHints = 1;
+
     static {
         // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
         assert (DetailedAsserts = true) == true;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java	Thu May 03 11:05:46 2012 +0200
@@ -82,7 +82,7 @@
         return GraalOptions.RemoveNeverExecutedCode && enabledOpts.contains(Optimization.RemoveNeverExecutedCode);
     }
 
-    public boolean useUseTypeCheckHints() {
+    public boolean useTypeCheckHints() {
         return GraalOptions.UseTypeCheckHints && enabledOpts.contains(Optimization.UseTypeCheckHints);
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/debug/package-info.java	Fri Apr 27 13:13:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-/**
- * A collection of debugging aids for Graal development.
- */
-package com.oracle.graal.compiler.debug;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu May 03 11:05:46 2012 +0200
@@ -484,7 +484,7 @@
         return !(location instanceof IndexedLocationNode) && location.displacement() < 4096;
     }
 
-    private void emitPrologue() {
+    protected void emitPrologue() {
         CiCallingConvention incomingArguments = frameMap.registerConfig.getCallingConvention(JavaCallee, CiUtil.signatureToKinds(method), target, false);
 
         CiValue[] params = new CiValue[incomingArguments.locations.length];
@@ -509,10 +509,8 @@
 
     @Override
     public void visitCheckCast(CheckCastNode x) {
-        if (x.emitCode()) {
-            XirSnippet snippet = xir.genCheckCast(site(x, x.object()), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass(), x.hints(), x.hintsExact());
-            emitXir(snippet, x, state(), true);
-        }
+        XirSnippet snippet = xir.genCheckCast(site(x, x.object()), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass(), x.hints(), x.hintsExact());
+        emitXir(snippet, x, state(), true);
         // The result of a checkcast is the unmodified object, so no need to allocate a new variable for it.
         setResult(x, operand(x.object()));
     }
@@ -914,11 +912,9 @@
     protected abstract LabelRef createDeoptStub(RiDeoptAction action, RiDeoptReason reason, LIRDebugInfo info, Object deoptInfo);
 
     @Override
-    public Variable emitCallToRuntime(CiRuntimeCall runtimeCall, boolean canTrap, CiValue... args) {
+    public Variable emitCall(@SuppressWarnings("hiding") Object target, CiKind result, CiKind[] arguments, boolean canTrap, CiValue... args) {
         LIRDebugInfo info = canTrap ? state() : null;
 
-        CiKind result = runtimeCall.resultKind;
-        CiKind[] arguments = runtimeCall.arguments;
         CiValue physReg = resultOperandFor(result);
 
         List<CiValue> argumentList;
@@ -939,7 +935,7 @@
             argumentList = Collections.emptyList();
         }
 
-        emitCall(runtimeCall, physReg, argumentList, CiConstant.forLong(0), info, null);
+        emitCall(target, physReg, argumentList, CiConstant.forLong(0), info, null);
 
         if (isLegal(physReg)) {
             return emitMove(physReg);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java	Thu May 03 11:05:46 2012 +0200
@@ -70,7 +70,6 @@
             METRIC_PROCESSED_NODES.increment();
             if (node instanceof Canonicalizable) {
                 METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
-                Debug.log("Canonicalizer: work on %s", node);
                 graph.mark();
                 ValueNode canonical = ((Canonicalizable) node).canonical(tool);
 //     cases:                                           original node:
@@ -85,7 +84,11 @@
 //                          Fixed-connected|   2    |        X        |       6       |
 //                                         --------------------------------------------
 //       X: must not happen (checked with assertions)
-                if (canonical != node) {
+                if (canonical == node) {
+                    Debug.log("Canonicalizer: work on %s", node);
+                } else {
+                    Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
+
                     METRIC_CANONICALIZED_NODES.increment();
                     if (node instanceof FloatingNode) {
                         if (canonical == null) {
@@ -122,6 +125,7 @@
                     nodeWorkList.addAll(graph.getNewNodes());
                 }
             } else if (node instanceof Simplifiable) {
+                Debug.log("Canonicalizer: simplifying %s", node);
                 METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment();
                 ((Simplifiable) node).simplify(tool);
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java	Thu May 03 11:05:46 2012 +0200
@@ -80,7 +80,7 @@
 
     @SuppressWarnings("unchecked")
     @Override
-    protected void run(StructuredGraph graph) {
+    protected void run(final StructuredGraph graph) {
         graph.createNodeMap();
 
         if (hints != null) {
@@ -91,8 +91,16 @@
         }
 
         while (!inlineCandidates.isEmpty() && graph.getNodeCount() < GraalOptions.MaximumDesiredSize) {
-            InlineInfo info = inlineCandidates.remove();
-            if (info.invoke.node().isAlive() && inliningPolicy.isWorthInlining(graph, info)) {
+            final InlineInfo info = inlineCandidates.remove();
+
+            boolean inline = Debug.scope("InliningDecisions", new Callable<Boolean>() {
+                @Override
+                public Boolean call() throws Exception {
+                    return info.invoke.node().isAlive() && inliningPolicy.isWorthInlining(graph, info);
+                }
+            });
+
+            if (inline) {
                 Iterable<Node> newNodes = null;
                 try {
                     info.inline(graph, runtime, this);
@@ -124,24 +132,35 @@
         }
 
         if (GraalOptions.Debug && graph.getNodeCount() >= GraalOptions.MaximumDesiredSize) {
-            Debug.log("inlining cut off by MaximumDesiredSize");
+            Debug.scope("InliningDecisions", new Runnable() {
+                public void run() {
+                    for (InlineInfo info : inlineCandidates) {
+                        Debug.log("not inlining %s because inlining cut off by MaximumDesiredSize", InliningUtil.methodName(info));
+                    }
+                }
+            });
+
             metricInliningStoppedByMaxDesiredSize.increment();
         }
     }
 
-    private void scanInvokes(Iterable<? extends Node> newNodes, int level, StructuredGraph graph) {
-        graph.mark();
-        for (Node node : newNodes) {
-            if (node != null) {
-                if (node instanceof Invoke) {
-                    Invoke invoke = (Invoke) node;
-                    scanInvoke(invoke, level);
-                }
-                for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) {
-                    scanInvoke((Invoke) usage, level);
+    private void scanInvokes(final Iterable<? extends Node> newNodes, final int level, final StructuredGraph graph) {
+        Debug.scope("InliningDecisions", new Runnable() {
+            public void run() {
+                graph.mark();
+                for (Node node : newNodes) {
+                    if (node != null) {
+                        if (node instanceof Invoke) {
+                            Invoke invoke = (Invoke) node;
+                            scanInvoke(invoke, level);
+                        }
+                        for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) {
+                            scanInvoke((Invoke) usage, level);
+                        }
+                    }
                 }
             }
-        }
+        });
     }
 
     private void scanInvoke(Invoke invoke, int level) {
@@ -282,11 +301,11 @@
 
             double penalty = Math.pow(GraalOptions.InliningSizePenaltyExp, callerGraph.getNodeCount() / (double) GraalOptions.MaximumDesiredSize) / GraalOptions.InliningSizePenaltyExp;
             if (info.weight > GraalOptions.MaximumInlineWeight / (1 + penalty * GraalOptions.InliningSizePenalty)) {
-                Debug.log("not inlining (cut off by weight %e): %s", info.weight, info);
+                Debug.log("not inlining %s (cut off by weight %e)", InliningUtil.methodName(info), info.weight);
                 return false;
             }
 
-            Debug.log("inlining (weight %f): %s", info.weight, info);
+            Debug.log("inlining %s (weight %f): %s", InliningUtil.methodName(info), info.weight);
             return true;
         }
     }
@@ -361,15 +380,15 @@
     private static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) {
         boolean success = info.weight <= maxSize;
         if (DebugScope.getInstance().isLogEnabled()) {
-            String formatterString = success ? "inlining invoke at %s@%d (size %f <= %f): %s" : "not inlining invoke at %s@%d (too large %f > %f): %s";
-            Debug.log(formatterString, CiUtil.format("%H.%n(%p):%r", info.invoke.stateAfter().method()), info.invoke.bci(), info.weight, maxSize, info);
+            String formatterString = success ? "inlining %s (size %f <= %f)" : "not inlining %s (too large %f > %f)";
+            Debug.log(formatterString, InliningUtil.methodName(info), info.weight, maxSize);
         }
         return success;
     }
 
     private static boolean checkCompiledCodeSize(InlineInfo info) {
         if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) {
-            Debug.log("not inlining invoke at %s@%d (CompiledCodeSize %d > %d): %s", CiUtil.format("%H.%n(%p):%r", info.invoke.stateAfter().method()), info.invoke.bci(), info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize, info);
+            Debug.log("not inlining %s (CompiledCodeSize %d > %d)", InliningUtil.methodName(info), info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize);
             return false;
         }
         return true;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/UnscheduleNodes.java	Fri Apr 27 13:13:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.schedule;
-
-import java.util.*;
-
-import com.oracle.graal.compiler.graph.*;
-import com.oracle.graal.compiler.types.*;
-import com.oracle.graal.nodes.*;
-
-class UnscheduleState implements MergeableState<UnscheduleState> {
-
-    public FixedWithNextNode last;
-
-    @Override
-    public boolean merge(MergeNode merge, List<UnscheduleState> withStates) {
-        last = null;
-        return true;
-    }
-
-    @Override
-    public void loopBegin(LoopBeginNode loop) {
-        last = null;
-    }
-
-    @Override
-    public void loopEnds(LoopBeginNode loop, List<UnscheduleState> loopEndStates) {
-        last = null;
-    }
-
-    @Override
-    public void afterSplit(FixedNode node) {
-        last = null;
-    }
-
-    @Override
-    public UnscheduleState clone() {
-        return new UnscheduleState();
-    }
-}
-
-public class UnscheduleNodes extends ScheduledNodeIterator<UnscheduleState> {
-
-    public UnscheduleNodes(FixedNode start) {
-        super(start, new UnscheduleState());
-    }
-
-    @Override
-    protected void node(ScheduledNode node) {
-        if (node instanceof FixedNode) {
-            if (state.last != null) {
-                state.last.setNext((FixedNode) node);
-            }
-            if (node instanceof FixedWithNextNode) {
-                state.last = (FixedWithNextNode) node;
-            }
-        } else {
-            node.setScheduledNext(null);
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java	Thu May 03 11:05:46 2012 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.target;
+
+import com.oracle.graal.compiler.gen.*;
+
+public interface LIRGenLowerable {
+
+    void generate(LIRGenerator generator);
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Thu May 03 11:05:46 2012 +0200
@@ -37,6 +37,7 @@
 import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
 import com.oracle.max.cri.xir.*;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
@@ -102,8 +103,8 @@
 
     @Override
     protected void emitNode(ValueNode node) {
-        if (node instanceof AMD64LIRLowerable) {
-            ((AMD64LIRLowerable) node).generateAmd64(this);
+        if (node instanceof LIRGenLowerable) {
+            ((LIRGenLowerable) node).generate(this);
         } else {
             super.emitNode(node);
         }
@@ -338,7 +339,7 @@
     }
 
     @Override
-    public Variable emitRem(CiValue a, CiValue b) {
+    public CiValue emitRem(CiValue a, CiValue b) {
         switch(a.kind) {
             case Int:
                 emitMove(a, RAX_I);
@@ -349,9 +350,9 @@
                 append(new DivOp(LREM, RDX_L, RAX_L, load(b), state()));
                 return emitMove(RDX_L);
             case Float:
-                return emitCallToRuntime(CiRuntimeCall.ArithmeticFrem, false, a, b);
+                return emitCall(CiRuntimeCall.ArithmeticFrem, false, a, b);
             case Double:
-                return emitCallToRuntime(CiRuntimeCall.ArithmeticDrem, false, a, b);
+                return emitCall(CiRuntimeCall.ArithmeticDrem, false, a, b);
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRLowerable.java	Fri Apr 27 13:13:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.target.amd64;
-
-public interface AMD64LIRLowerable {
-
-    void generateAmd64(AMD64LIRGenerator generator);
-}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Thu May 03 11:05:46 2012 +0200
@@ -26,9 +26,6 @@
 import java.util.*;
 import java.util.concurrent.*;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.cri.ri.RiType.Representation;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.cri.*;
@@ -40,7 +37,11 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.cri.ri.RiTypeProfile.ProfiledType;
 
 public class InliningUtil {
 
@@ -51,21 +52,35 @@
         void recordConcreteMethodAssumption(RiResolvedMethod method, RiResolvedType context, RiResolvedMethod impl);
     }
 
-    private static String methodName(RiResolvedMethod method, Invoke invoke) {
-        if (Debug.isLogEnabled()) {
-            if (invoke != null && invoke.stateAfter() != null) {
-                RiMethod parent = invoke.stateAfter().method();
-                return parent.name() + "@" + invoke.bci() + ": " + methodNameAndCodeSize(method);
-            } else {
-                return methodNameAndCodeSize(method);
-            }
+    public static String methodName(RiResolvedMethod method, Invoke invoke) {
+        if (!Debug.isLogEnabled()) {
+            return null;
+        } else if (invoke != null && invoke.stateAfter() != null) {
+            return methodName(invoke.stateAfter(), invoke.bci()) + ": " + CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
         } else {
-            return null;
+            return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
         }
     }
 
-    private static String methodNameAndCodeSize(RiResolvedMethod method) {
-        return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
+    public static String methodName(InlineInfo info) {
+        if (!Debug.isLogEnabled()) {
+            return null;
+        } else if (info.invoke != null && info.invoke.stateAfter() != null) {
+            return methodName(info.invoke.stateAfter(), info.invoke.bci()) + ": " + info.toString();
+        } else {
+            return info.toString();
+        }
+    }
+
+    private static String methodName(FrameState frameState, int bci) {
+        StringBuilder sb = new StringBuilder();
+        if (frameState.outerFrameState() != null) {
+            sb.append(methodName(frameState.outerFrameState(), frameState.outerFrameState().bci));
+            sb.append("->");
+        }
+        sb.append(CiUtil.format("%h.%n", frameState.method()));
+        sb.append("@").append(bci);
+        return sb.toString();
     }
 
     /**
@@ -179,8 +194,8 @@
             AnchorNode anchor = graph.add(new AnchorNode());
             assert invoke.predecessor() != null;
 
-            CheckCastNode checkCast = createAnchoredReceiver(graph, runtime, anchor, type, receiver);
-            invoke.callTarget().replaceFirstInput(receiver, checkCast);
+            ValueNode anchoredReceiver = createAnchoredReceiver(graph, anchor, type, receiver);
+            invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver);
 
             graph.addBeforeFixed(invoke.node(), objectClass);
             graph.addBeforeFixed(invoke.node(), guard);
@@ -209,21 +224,19 @@
      */
     private static class MultiTypeGuardInlineInfo extends InlineInfo {
         public final List<RiResolvedMethod> concretes;
-        public final RiResolvedType[] types;
+        public final ProfiledType[] ptypes;
         public final int[] typesToConcretes;
-        public final double[] typeProbabilities;
         public final double notRecordedTypeProbability;
 
-        public MultiTypeGuardInlineInfo(Invoke invoke, double weight, int level, List<RiResolvedMethod> concretes, RiResolvedType[] types,
-                        int[] typesToConcretes, double[] typeProbabilities, double notRecordedTypeProbability) {
+        public MultiTypeGuardInlineInfo(Invoke invoke, double weight, int level, List<RiResolvedMethod> concretes, ProfiledType[] ptypes,
+                        int[] typesToConcretes, double notRecordedTypeProbability) {
             super(invoke, weight, level);
-            assert concretes.size() > 0 && concretes.size() <= types.length : "must have at least one method but no more than types methods";
-            assert types.length == typesToConcretes.length && types.length == typeProbabilities.length : "array length must match";
+            assert concretes.size() > 0 && concretes.size() <= ptypes.length : "must have at least one method but no more than types methods";
+            assert ptypes.length == typesToConcretes.length : "array lengths must match";
 
             this.concretes = concretes;
-            this.types = types;
+            this.ptypes = ptypes;
             this.typesToConcretes = typesToConcretes;
-            this.typeProbabilities = typeProbabilities;
             this.notRecordedTypeProbability = notRecordedTypeProbability;
         }
 
@@ -291,7 +304,7 @@
                 for (int j = 0; j < typesToConcretes.length; j++) {
                     if (typesToConcretes[j] == i) {
                         predecessors++;
-                        probability += typeProbabilities[j];
+                        probability += ptypes[j].probability;
                     }
                 }
 
@@ -334,8 +347,8 @@
 
                 RiResolvedType commonType = getLeastCommonType(i);
                 ValueNode receiver = invokeForInlining.callTarget().receiver();
-                CheckCastNode checkCast = createAnchoredReceiver(graph, runtime, node, commonType, receiver);
-                invokeForInlining.callTarget().replaceFirstInput(receiver, checkCast);
+                ValueNode anchoredReceiver = createAnchoredReceiver(graph, node, commonType, receiver);
+                invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver);
 
                 RiResolvedMethod concrete = concretes.get(i);
                 StructuredGraph calleeGraph = getGraph(concrete, callback);
@@ -350,9 +363,9 @@
             for (int i = 0; i < typesToConcretes.length; i++) {
                 if (typesToConcretes[i] == concreteMethodIndex) {
                     if (commonType == null) {
-                        commonType = types[i];
+                        commonType = ptypes[i].type;
                     } else {
-                        commonType = commonType.leastCommonAncestor(types[i]);
+                        commonType = commonType.leastCommonAncestor(ptypes[i].type);
                     }
                 }
             }
@@ -361,7 +374,7 @@
         }
 
         private void inlineSingleMethod(StructuredGraph graph, GraalRuntime runtime, InliningCallback callback) {
-            assert concretes.size() == 1 && types.length > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
+            assert concretes.size() == 1 && ptypes.length > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
 
             MergeNode calleeEntryNode = graph.add(new MergeNode());
             calleeEntryNode.setProbability(invoke.probability());
@@ -383,15 +396,15 @@
         }
 
         private FixedNode createDispatchOnType(StructuredGraph graph, ReadHubNode objectClassNode, BeginNode[] calleeEntryNodes, FixedNode unknownTypeSux) {
-            assert types.length > 1;
+            assert ptypes.length > 1;
 
-            int lastIndex = types.length - 1;
-            double[] branchProbabilities = convertTypeToBranchProbabilities(typeProbabilities, notRecordedTypeProbability);
-            double nodeProbability = typeProbabilities[lastIndex];
-            IfNode nextNode = createTypeCheck(graph, objectClassNode, types[lastIndex], calleeEntryNodes[typesToConcretes[lastIndex]], unknownTypeSux, branchProbabilities[lastIndex], invoke.probability() * nodeProbability);
+            int lastIndex = ptypes.length - 1;
+            double[] branchProbabilities = convertTypeToBranchProbabilities(ptypes, notRecordedTypeProbability);
+            double nodeProbability = ptypes[lastIndex].probability;
+            IfNode nextNode = createTypeCheck(graph, objectClassNode, ptypes[lastIndex].type, calleeEntryNodes[typesToConcretes[lastIndex]], unknownTypeSux, branchProbabilities[lastIndex], invoke.probability() * nodeProbability);
             for (int i = lastIndex - 1; i >= 0; i--) {
-                nodeProbability += typeProbabilities[i];
-                nextNode = createTypeCheck(graph, objectClassNode, types[i], calleeEntryNodes[typesToConcretes[i]], nextNode, branchProbabilities[i], invoke.probability() * nodeProbability);
+                nodeProbability += ptypes[i].probability;
+                nextNode = createTypeCheck(graph, objectClassNode, ptypes[i].type, calleeEntryNodes[typesToConcretes[i]], nextNode, branchProbabilities[i], invoke.probability() * nodeProbability);
             }
 
             return nextNode;
@@ -411,12 +424,12 @@
             return result;
         }
 
-        private static double[] convertTypeToBranchProbabilities(double[] typeProbabilities, double notRecordedTypeProbability) {
-            double[] result = new double[typeProbabilities.length];
+        private static double[] convertTypeToBranchProbabilities(ProfiledType[] ptypes, double notRecordedTypeProbability) {
+            double[] result = new double[ptypes.length];
             double total = notRecordedTypeProbability;
-            for (int i = typeProbabilities.length - 1; i >= 0; i--) {
-                total += typeProbabilities[i];
-                result[i] = typeProbabilities[i] / total;
+            for (int i = ptypes.length - 1; i >= 0; i--) {
+                total += ptypes[i].probability;
+                result[i] = ptypes[i].probability / total;
             }
             assert total > 0.99 && total < 1.01;
             return result;
@@ -483,7 +496,7 @@
         @Override
         public String toString() {
             StringBuilder builder = new StringBuilder(shouldFallbackToInvoke() ? "megamorphic" : "polymorphic");
-            builder.append(String.format(", %d methods with %d type checks:", concretes.size(), types.length));
+            builder.append(String.format(", %d methods with %d type checks:", concretes.size(), ptypes.length));
             for (int i = 0; i < concretes.size(); i++) {
                 builder.append(CiUtil.format("  %H.%n(%p):%r", concretes.get(i)));
             }
@@ -598,15 +611,13 @@
         RiProfilingInfo profilingInfo = parent.profilingInfo();
         RiTypeProfile typeProfile = profilingInfo.getTypeProfile(invoke.bci());
         if (typeProfile != null) {
-            RiResolvedType[] types = typeProfile.getTypes();
-            double[] probabilities = typeProfile.getProbabilities();
+            ProfiledType[] ptypes = typeProfile.getTypes();
 
-            if (types != null && probabilities != null && types.length > 0) {
-                assert types.length == probabilities.length : "length must match";
+            if (ptypes != null && ptypes.length > 0) {
                 double notRecordedTypeProbability = typeProfile.getNotRecordedProbability();
-                if (types.length == 1 && notRecordedTypeProbability == 0) {
+                if (ptypes.length == 1 && notRecordedTypeProbability == 0) {
                     if (optimisticOpts.inlineMonomorphicCalls()) {
-                        RiResolvedType type = types[0];
+                        RiResolvedType type = ptypes[0].type;
                         RiResolvedMethod concrete = type.resolveMethodImpl(targetMethod);
                         if (checkTargetConditions(invoke, concrete, optimisticOpts)) {
                             double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
@@ -632,9 +643,9 @@
 
                         // determine concrete methods and map type to specific method
                         ArrayList<RiResolvedMethod> concreteMethods = new ArrayList<>();
-                        int[] typesToConcretes = new int[types.length];
-                        for (int i = 0; i < types.length; i++) {
-                            RiResolvedMethod concrete = types[i].resolveMethodImpl(targetMethod);
+                        int[] typesToConcretes = new int[ptypes.length];
+                        for (int i = 0; i < ptypes.length; i++) {
+                            RiResolvedMethod concrete = ptypes[i].type.resolveMethodImpl(targetMethod);
 
                             int index = concreteMethods.indexOf(concrete);
                             if (index < 0) {
@@ -655,7 +666,7 @@
                         }
 
                         if (canInline) {
-                            return new MultiTypeGuardInlineInfo(invoke, totalWeight, level, concreteMethods, types, typesToConcretes, probabilities, notRecordedTypeProbability);
+                            return new MultiTypeGuardInlineInfo(invoke, totalWeight, level, concreteMethods, ptypes, typesToConcretes, notRecordedTypeProbability);
                         } else {
                             Debug.log("not inlining %s because it is a polymorphic method call and at least one invoked method cannot be inlined", methodName(targetMethod, invoke));
                             return null;
@@ -679,11 +690,9 @@
         }
     }
 
-    private static CheckCastNode createAnchoredReceiver(StructuredGraph graph, GraalRuntime runtime, FixedNode anchor, RiResolvedType commonType, ValueNode receiver) {
+    private static ValueNode createAnchoredReceiver(StructuredGraph graph, FixedNode anchor, RiResolvedType commonType, ValueNode receiver) {
         // to avoid that floating reads on receiver fields float above the type check
-        ConstantNode typeConst = graph.unique(ConstantNode.forCiConstant(commonType.getEncoding(Representation.ObjectHub), runtime, graph));
-        CheckCastNode checkCast = graph.unique(new CheckCastNode(anchor, typeConst, commonType, receiver, false));
-        return checkCast;
+        return graph.unique(new PiNode(receiver, anchor, StampFactory.declaredNonNull(commonType)));
     }
 
     private static boolean checkInvokeConditions(Invoke invoke) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalInternalError.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalInternalError.java	Thu May 03 11:05:46 2012 +0200
@@ -29,9 +29,6 @@
  */
 public class GraalInternalError extends Error {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = 8776065085829593278L;
     private Node node;
     private Graph graph;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Thu May 03 11:05:46 2012 +0200
@@ -63,7 +63,7 @@
     }
 
     public boolean isMarked(Node node) {
-        check(node);
+        assert check(node);
         return bitMap.get(node.id());
     }
 
@@ -72,12 +72,12 @@
     }
 
     public void mark(Node node) {
-        check(node);
+        assert check(node);
         bitMap.set(node.id());
     }
 
     public void clear(Node node) {
-        check(node);
+        assert check(node);
         bitMap.clear(node.id());
     }
 
@@ -93,10 +93,11 @@
         bitMap.grow(graph.nodeIdCount());
     }
 
-    private void check(Node node) {
+    private boolean check(Node node) {
         assert node.graph() == graph : "this node is not part of the graph";
-        assert !isNew(node) : "this node (" + node.id() + ") was added to the graph after creating the node bitmap (" + bitMap.length() + ")";
-        assert node.isAlive() : "node " + node + " is deleted!";
+        assert !isNew(node) : "node was added to the graph after creating the node bitmap";
+        assert node.isAlive() : "node is deleted!";
+        return true;
     }
 
     @Override
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java	Thu May 03 11:05:46 2012 +0200
@@ -28,9 +28,6 @@
  */
 public class VerificationError extends GraalInternalError {
 
-    /**
-     * 
-     */
     private static final long serialVersionUID = 8459607567446819822L;
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerObject.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerObject.java	Thu May 03 11:05:46 2012 +0200
@@ -29,9 +29,6 @@
  * Parent class for all HotSpot Ri... types.
  */
 public abstract class CompilerObject implements Serializable {
-    /**
-     * 
-     */
     private static final long serialVersionUID = -4551670987101214877L;
     protected final Compiler compiler;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Thu May 03 11:05:46 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot;
 
+import java.io.*;
 import java.util.concurrent.*;
 
 import com.oracle.graal.compiler.*;
@@ -57,7 +58,8 @@
     public void run() {
         if (GraalOptions.Debug) {
             Debug.enable();
-            HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, GraalOptions.LogFile);
+            PrintStream log = CompilerImpl.getInstance().getVMToCompiler().log();
+            HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log);
             Debug.setConfig(hotspotDebugConfig);
         }
         super.run();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Thu May 03 11:05:46 2012 +0200
@@ -43,10 +43,7 @@
     private final List<DebugDumpHandler> dumpHandlers = new ArrayList<>();
     private final PrintStream output;
 
-    private static final PrintStream cachedOut = System.out;
-
-
-    public HotSpotDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter, String logFile) {
+    public HotSpotDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter, PrintStream output) {
         this.logFilter = DebugFilter.parse(logFilter);
         this.meterFilter = DebugFilter.parse(meterFilter);
         this.timerFilter = DebugFilter.parse(timerFilter);
@@ -72,15 +69,7 @@
             dumpHandlers.add(new IdealGraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintIdealGraphPort));
         }
         dumpHandlers.add(new CFGPrinterObserver());
-        if (logFile == null || logFile.isEmpty()) {
-            output = cachedOut;
-        } else {
-            try {
-                output = new PrintStream(logFile);
-            } catch (FileNotFoundException e) {
-                throw new RuntimeException("couldn't create log file: " + logFile, e);
-            }
-        }
+        this.output = output;
     }
 
     public boolean isLogEnabled() {
@@ -163,10 +152,12 @@
         Debug.log(String.format("Exception occured in scope: %s", Debug.currentScope()));
         for (Object o : Debug.context()) {
             Debug.log("Context obj %s", o);
-            if (o instanceof Graph && GraalOptions.DumpOnError) {
-                Graph graph = (Graph) o;
-                Debug.log("Found graph in context: ", graph);
-                Debug.dump(o, "Exception graph");
+            if (o instanceof Graph) {
+                if (GraalOptions.DumpOnError) {
+                    Debug.dump(o, "Exception graph");
+                } else {
+                    Debug.log("Use -G:+DumpOnError to enable dumping of graphs on this error");
+                }
             }
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetMethod.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetMethod.java	Thu May 03 11:05:46 2012 +0200
@@ -34,9 +34,6 @@
  */
 public final class HotSpotTargetMethod extends CompilerObject {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = 7807321392203253218L;
     public final CiTargetMethod targetMethod;
     public final HotSpotMethodResolved method; // used only for methods
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu May 03 11:05:46 2012 +0200
@@ -29,9 +29,6 @@
  */
 public final class HotSpotVMConfig extends CompilerObject {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = -4744897993263044184L;
 
     private HotSpotVMConfig() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu May 03 11:05:46 2012 +0200
@@ -119,5 +119,7 @@
 
     long[] getDeoptedLeafGraphIds();
 
+    String decodePC(long pc);
+
     // Checkstyle: resume
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu May 03 11:05:46 2012 +0200
@@ -171,5 +171,8 @@
     @Override
     public native long[] getDeoptedLeafGraphIds();
 
+    @Override
+    public native String decodePC(long pc);
+
     // Checkstyle: resume
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Thu May 03 11:05:46 2012 +0200
@@ -23,9 +23,13 @@
 
 package com.oracle.graal.hotspot.bridge;
 
+import java.io.*;
+
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.hotspot.ri.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.graal.hotspot.ri.*;
 
 /**
  * Calls from HotSpot into Java.
@@ -40,6 +44,8 @@
 
     void bootstrap() throws Throwable;
 
+    PrintStream log();
+
     RiMethod createRiMethodUnresolved(String name, String signature, RiType holder);
 
     RiSignature createRiSignature(String signature);
@@ -59,4 +65,6 @@
     CiConstant createCiConstantDouble(double value);
 
     CiConstant createCiConstantObject(Object object);
+
+    PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu May 03 11:05:46 2012 +0200
@@ -23,6 +23,7 @@
 
 package com.oracle.graal.hotspot.bridge;
 
+import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
@@ -35,6 +36,7 @@
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.Compiler;
+import com.oracle.graal.hotspot.counters.*;
 import com.oracle.graal.hotspot.ri.*;
 import com.oracle.graal.hotspot.server.*;
 import com.oracle.graal.hotspot.snippets.*;
@@ -66,6 +68,8 @@
     private ThreadPoolExecutor slowCompileQueue;
     private AtomicInteger compileTaskIds = new AtomicInteger();
 
+    private PrintStream log = System.out;
+
     public VMToCompilerImpl(Compiler compiler) {
         this.compiler = compiler;
 
@@ -81,8 +85,16 @@
     }
 
     public void startCompiler() throws Throwable {
-        // Make sure TTY is initialized here such that the correct System.out is used for TTY.
-        TTY.initialize();
+        if (GraalOptions.LogFile != null) {
+            try {
+                final boolean enableAutoflush = true;
+                log = new PrintStream(new FileOutputStream(GraalOptions.LogFile), enableAutoflush);
+            } catch (FileNotFoundException e) {
+                throw new RuntimeException("couldn't open log file: " + GraalOptions.LogFile, e);
+            }
+        }
+
+        TTY.initialize(log);
 
         if (GraalOptions.Log == null && GraalOptions.Meter == null && GraalOptions.Time == null && GraalOptions.Dump == null) {
             if (GraalOptions.MethodFilter != null) {
@@ -92,7 +104,7 @@
 
         if (GraalOptions.Debug) {
             Debug.enable();
-            HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, GraalOptions.LogFile);
+            HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log);
             Debug.setConfig(hotspotDebugConfig);
         }
         // Install intrinsics.
@@ -211,6 +223,7 @@
         }
         System.gc();
         CiCompilationStatistics.clear("bootstrap2");
+        MethodEntryCounters.printCounters(compiler);
     }
 
     private void enqueue(Method m) throws Throwable {
@@ -264,6 +277,8 @@
             }
         }
         CiCompilationStatistics.clear("final");
+        MethodEntryCounters.printCounters(compiler);
+        HotSpotXirGenerator.printCounters(TTY.out().out());
     }
 
     private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) {
@@ -349,7 +364,7 @@
 
             final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method);
             int id = compileTaskIds.incrementAndGet();
-            CompilationTask task = CompilationTask.create(compiler, createHotSpotSpecificPhasePlan(optimisticOpts), optimisticOpts, method, id, priority);
+            CompilationTask task = CompilationTask.create(compiler, createPhasePlan(optimisticOpts), optimisticOpts, method, id, priority);
             if (blocking) {
                 task.runCompilation();
             } else {
@@ -461,7 +476,7 @@
     }
 
 
-    private PhasePlan createHotSpotSpecificPhasePlan(OptimisticOptimizations optimisticOpts) {
+    public PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts) {
         PhasePlan phasePlan = new PhasePlan();
         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
@@ -470,4 +485,9 @@
         }
         return phasePlan;
     }
+
+    @Override
+    public PrintStream log() {
+        return log;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java	Thu May 03 11:05:46 2012 +0200
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2012, 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.counters;
+
+import static com.oracle.max.cri.ci.CiValueUtil.*;
+
+import java.util.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.Compiler;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.criutils.*;
+
+
+public class MethodEntryCounters {
+    protected static final class Counter implements Comparable<Counter> {
+        protected static ArrayList<Counter> counters = new ArrayList<>();
+
+        protected final String method;
+        protected final long[] counts = new long[GraalOptions.MethodEntryCountersCallers * 2 + 2];
+
+        protected long sortCount;
+
+        protected Counter(RiResolvedMethod method) {
+            this.method = CiUtil.format("%H.%n", method);
+            counters.add(this);
+        }
+
+        @Override
+        public int compareTo(Counter o) {
+            return (int) (o.sortCount - sortCount);
+        }
+    }
+
+
+    protected static class AMD64MethodEntryOp extends AMD64LIRInstruction {
+        protected static int codeSize;
+
+        protected final Counter counter;
+
+        protected AMD64MethodEntryOp(Counter counter, CiValue counterArr, CiValue callerPc) {
+            super("ENTRY_COUNTER", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, new CiValue[] {counterArr, callerPc});
+            this.counter = counter;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            int start = masm.codeBuffer.position();
+
+            CiValue counterArr = temp(0);
+            CiValue callerPc = temp(1);
+
+            int off = Unsafe.getUnsafe().arrayBaseOffset(long[].class);
+            int scale = Unsafe.getUnsafe().arrayIndexScale(long[].class);
+
+            AMD64Move.move(tasm, masm, counterArr, CiConstant.forObject(counter.counts));
+            AMD64Move.load(tasm, masm, callerPc, new CiAddress(CiKind.Long, AMD64.rbp.asValue(CiKind.Long), 8), null);
+
+            Label done = new Label();
+            for (int i = 0; i < counter.counts.length - 2; i += 2) {
+                CiAddress counterPcAddr = new CiAddress(CiKind.Long, counterArr, i * scale + off);
+                CiAddress counterValueAddr = new CiAddress(CiKind.Long, counterArr, (i + 1) * scale + off);
+
+                Label skipClaim = new Label();
+                masm.cmpq(counterPcAddr, 0);
+                masm.jccb(ConditionFlag.notEqual, skipClaim);
+                AMD64Move.store(tasm, masm, counterPcAddr, callerPc, null);
+                masm.bind(skipClaim);
+
+                Label skipInc = new Label();
+                masm.cmpq(counterPcAddr, asRegister(callerPc));
+                masm.jccb(ConditionFlag.notEqual, skipInc);
+                masm.addq(counterValueAddr, 1);
+                masm.jmp(done);
+                masm.bind(skipInc);
+            }
+
+            CiAddress counterValueAddr = new CiAddress(CiKind.Long, counterArr, (counter.counts.length - 1) * scale + off);
+            masm.addq(counterValueAddr, 1);
+            masm.bind(done);
+
+            int size = masm.codeBuffer.position() - start;
+            assert codeSize == 0 || codeSize == size;
+            codeSize = size;
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Temp && index == 0) {
+                return EnumSet.of(OperandFlag.Register);
+            } else if (mode == OperandMode.Temp && index == 1) {
+                return EnumSet.of(OperandFlag.Register);
+            }
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+
+    public static void emitCounter(LIRGenerator gen, RiResolvedMethod method) {
+        if (!GraalOptions.MethodEntryCounters) {
+            return;
+        }
+        gen.append(new AMD64MethodEntryOp(new Counter(method), gen.newVariable(CiKind.Long), gen.newVariable(CiKind.Long)));
+    }
+
+    public static int getCodeSize() {
+        if (!GraalOptions.MethodEntryCounters) {
+            return 0;
+        }
+        return AMD64MethodEntryOp.codeSize;
+    }
+
+
+    public static void printCounters(Compiler compiler) {
+        if (!GraalOptions.MethodEntryCounters) {
+            return;
+        }
+        ArrayList<Counter> copy = new ArrayList<>(Counter.counters);
+        long total = 0;
+        for (Counter counter : copy) {
+            long sum = 0;
+            for (int i = 0; i < counter.counts.length; i += 2) {
+                sum += counter.counts[i + 1];
+            }
+            counter.sortCount = sum;
+            total += sum;
+        }
+        Collections.sort(copy);
+
+        TTY.println();
+        TTY.println("** Compiled method invocation counters **");
+        for (Counter counter : copy) {
+            TTY.println("%16d %5.2f%%  %s", counter.sortCount, (double) counter.sortCount / total * 100d, counter.method);
+
+            if (counter.counts.length > 2) {
+                for (int i = 0; i < counter.counts.length; i += 2) {
+                    if (counter.counts[i] != 0 || counter.counts[i + 1] != 0) {
+                        TTY.print("              %16d  %5.2f%%", counter.counts[i + 1], (double) counter.counts[i + 1] / counter.sortCount * 100d);
+                        if (counter.counts[i] == 0) {
+                            TTY.println("  [other callers]");
+                        } else {
+                            TTY.println("  %x  %s", counter.counts[i], compiler.getCompilerToVM().decodePC(counter.counts[i]));
+                        }
+                        counter.counts[i] = 0;
+                        counter.counts[i + 1] = 0;
+                    }
+                }
+            }
+        }
+        TTY.println("** Compiled method invocation counters **");
+        TTY.println();
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotExceptionHandler.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotExceptionHandler.java	Thu May 03 11:05:46 2012 +0200
@@ -27,9 +27,6 @@
 
 
 public final class HotSpotExceptionHandler extends CompilerObject implements RiExceptionHandler {
-    /**
-     *
-     */
     private static final long serialVersionUID = 7110038548061733686L;
     private int startBci;
     private int endBci;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotField.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotField.java	Thu May 03 11:05:46 2012 +0200
@@ -38,9 +38,6 @@
  */
 public class HotSpotField extends CompilerObject implements RiResolvedField {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = 7692985878836955683L;
     private final RiResolvedType holder;
     private final String name;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotKlassOop.java	Thu May 03 11:05:46 2012 +0200
@@ -0,0 +1,47 @@
+/*
+ * 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.ri;
+
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.Compiler;
+
+/**
+ * A mechanism for safely conveying a HotSpot klassOop value from the compiler to the C++ code.
+ * Such values should not be directly exposed to Java code as they are not real Java
+ * objects. For instance, invoking a method on them or using them in an <code>instanceof</code>
+ * expression will most likely crash the VM.
+ */
+public class HotSpotKlassOop extends CompilerObject {
+
+    private static final long serialVersionUID = -5445542223575839143L;
+
+    /**
+     * The Java object from which the klassOop value can be derived (by the C++ code).
+     */
+    public final Class javaMirror;
+
+    HotSpotKlassOop(Compiler compiler, Class javaMirror) {
+        super(compiler);
+        this.javaMirror = javaMirror;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethod.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethod.java	Thu May 03 11:05:46 2012 +0200
@@ -28,9 +28,6 @@
 
 public abstract class HotSpotMethod extends CompilerObject implements RiMethod {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = 7167491397941960839L;
     protected String name;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodData.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodData.java	Thu May 03 11:05:46 2012 +0200
@@ -30,13 +30,11 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.Compiler;
 import com.oracle.max.cri.ri.*;
+import com.oracle.max.cri.ri.RiTypeProfile.*;
 
 
 public final class HotSpotMethodData extends CompilerObject {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = -8873133496591225071L;
 
     static {
@@ -335,8 +333,8 @@
         public RiTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
             int typeProfileWidth = config.typeProfileWidth;
 
-            RiResolvedType[] sparseTypes = new RiResolvedType[typeProfileWidth];
-            double[] counts = new double[typeProfileWidth];
+            RiResolvedType[] types = new RiResolvedType[typeProfileWidth];
+            long[] counts = new long[typeProfileWidth];
             long totalCount = 0;
             int entries = 0;
 
@@ -349,7 +347,9 @@
                         graalMirror = CompilerImpl.getInstance().getCompilerToVM().getType(javaClass);
                         assert graalMirror != null : "must not return null";
                     }
-                    sparseTypes[entries] = (RiResolvedType) graalMirror;
+
+
+                    types[entries] = (RiResolvedType) graalMirror;
 
                     long count = data.readUnsignedInt(position, getCountOffset(i));
                     totalCount += count;
@@ -360,7 +360,7 @@
             }
 
             totalCount += getTypesNotRecordedExecutionCount(data, position);
-            return createRiTypeProfile(sparseTypes, counts, totalCount, entries);
+            return createRiTypeProfile(types, counts, totalCount, entries);
         }
 
         protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
@@ -369,29 +369,24 @@
             return getCounterValue(data, position);
         }
 
-        private static RiTypeProfile createRiTypeProfile(RiResolvedType[] sparseTypes, double[] counts, long totalCount, int entries) {
-            RiResolvedType[] types;
-            double[] probabilities;
-
+        private static RiTypeProfile createRiTypeProfile(RiResolvedType[] types, long[] counts, long totalCount, int entries) {
             if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) {
                 return null;
-            } else if (entries < sparseTypes.length) {
-                types = Arrays.copyOf(sparseTypes, entries);
-                probabilities = new double[entries];
-            } else {
-                types = sparseTypes;
-                probabilities = counts;
             }
 
+            ProfiledType[] ptypes = new ProfiledType[entries];
             double totalProbability = 0.0;
             for (int i = 0; i < entries; i++) {
-                double p = counts[i] / totalCount;
-                probabilities[i] = p;
+                double p = counts[i];
+                p = p / totalCount;
                 totalProbability += p;
+                ptypes[i] = new ProfiledType(types[i], p);
             }
 
+            Arrays.sort(ptypes);
+
             double notRecordedTypeProbability = entries < config.typeProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability));
-            return new RiTypeProfile(types, notRecordedTypeProbability, probabilities);
+            return new RiTypeProfile(ptypes, notRecordedTypeProbability);
         }
 
         private static int getReceiverOffset(int row) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolved.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolved.java	Thu May 03 11:05:46 2012 +0200
@@ -29,7 +29,6 @@
 public interface HotSpotMethodResolved extends RiResolvedMethod, Remote {
 
     RiResolvedMethod uniqueConcreteMethod();
-    void dumpProfile();
     int vtableEntryOffset();
 
     void setCurrentTask(CompilationTask task);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Thu May 03 11:05:46 2012 +0200
@@ -27,12 +27,13 @@
 import java.util.*;
 import java.util.concurrent.*;
 
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.counters.*;
+import com.oracle.graal.java.bytecode.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.criutils.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.java.bytecode.*;
 
 /**
  * Implementation of RiMethod for resolved HotSpot methods.
@@ -186,7 +187,12 @@
     }
 
     public int compiledCodeSize() {
-        return compiler.getCompilerToVM().RiMethod_getCompiledCodeSize(this);
+        int result = compiler.getCompilerToVM().RiMethod_getCompiledCodeSize(this);
+        if (result > 0) {
+            assert result > MethodEntryCounters.getCodeSize();
+            result =  result - MethodEntryCounters.getCodeSize();
+        }
+        return result;
     }
 
     @Override
@@ -248,62 +254,6 @@
     }
 
     @Override
-    public void dumpProfile() {
-        TTY.println("profile info for %s", this);
-        TTY.println("canBeStaticallyBound: " + canBeStaticallyBound());
-        TTY.println("invocationCount: " + invocationCount());
-        RiProfilingInfo profilingInfo = this.profilingInfo();
-        for (int i = 0; i < codeSize(); i++) {
-            if (profilingInfo.getExecutionCount(i) != -1) {
-                TTY.println("  executionCount@%d: %d", i, profilingInfo.getExecutionCount(i));
-            }
-
-            if (profilingInfo.getBranchTakenProbability(i) != -1) {
-                TTY.println("  branchProbability@%d: %f", i, profilingInfo.getBranchTakenProbability(i));
-            }
-
-            double[] switchProbabilities = profilingInfo.getSwitchProbabilities(i);
-            if (switchProbabilities != null) {
-                TTY.print("  switchProbabilities@%d:", i);
-                for (int j = 0; j < switchProbabilities.length; j++) {
-                    TTY.print(" %f", switchProbabilities[j]);
-                }
-                TTY.println();
-            }
-
-            if (profilingInfo.getExceptionSeen(i) != RiExceptionSeen.FALSE) {
-                TTY.println("  exceptionSeen@%d: %s", i, profilingInfo.getExceptionSeen(i).name());
-            }
-
-            RiTypeProfile typeProfile = profilingInfo.getTypeProfile(i);
-            if (typeProfile != null) {
-                RiResolvedType[] types = typeProfile.getTypes();
-                double[] probabilities = typeProfile.getProbabilities();
-                if (types != null && probabilities != null) {
-                    assert types.length == probabilities.length : "length must match";
-                    TTY.print("  types@%d:", i);
-                    for (int j = 0; j < types.length; j++) {
-                        TTY.print(" %s (%f)", types[j], probabilities[j]);
-                    }
-                    TTY.println(" not recorded (%f)", typeProfile.getNotRecordedProbability());
-                }
-            }
-        }
-
-        boolean firstDeoptReason = true;
-        for (RiDeoptReason reason: RiDeoptReason.values()) {
-            int count = profilingInfo.getDeoptimizationCount(reason);
-            if (count > 0) {
-                if (firstDeoptReason) {
-                    TTY.println("Deopt History");
-                    firstDeoptReason = false;
-                }
-                TTY.println("  %s: %d", reason.name(), count);
-            }
-        }
-    }
-
-    @Override
     public Annotation[][] getParameterAnnotations() {
         if (isConstructor()) {
             Constructor javaConstructor = toJavaConstructor();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodUnresolved.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodUnresolved.java	Thu May 03 11:05:46 2012 +0200
@@ -29,9 +29,6 @@
  * Implementation of RiMethod for unresolved HotSpot methods.
  */
 public final class HotSpotMethodUnresolved extends HotSpotMethod {
-    /**
-     * 
-     */
     private static final long serialVersionUID = 5610263481791970079L;
     private final RiSignature signature;
     protected RiType holder;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotProfilingInfo.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotProfilingInfo.java	Thu May 03 11:05:46 2012 +0200
@@ -30,9 +30,6 @@
 
 public final class HotSpotProfilingInfo extends CompilerObject implements RiProfilingInfo {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = -8307682725047864875L;
     private static final DebugMetric metricInsufficentSpace = Debug.metric("InsufficientSpaceForProfilingData");
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Thu May 03 11:05:46 2012 +0200
@@ -28,8 +28,6 @@
 import java.util.*;
 
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.cri.*;
 import com.oracle.graal.graph.*;
@@ -37,7 +35,6 @@
 import com.oracle.graal.hotspot.Compiler;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.target.amd64.*;
-import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -495,10 +492,8 @@
 
     @Override
     public CiTargetMethod compile(RiResolvedMethod method, StructuredGraph graph) {
-        final PhasePlan plan = new PhasePlan();
-        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
-        plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-        return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), plan, OptimisticOptimizations.ALL);
+        OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL;
+        return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), compiler.getVMToCompiler().createPhasePlan(optimisticOpts), optimisticOpts);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotSignature.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotSignature.java	Thu May 03 11:05:46 2012 +0200
@@ -35,9 +35,6 @@
  */
 public class HotSpotSignature extends CompilerObject implements RiSignature {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = -2890917956072366116L;
     private final List<String> arguments = new ArrayList<>();
     private final String returnType;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotType.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotType.java	Thu May 03 11:05:46 2012 +0200
@@ -30,9 +30,6 @@
  * Common interface for all HotSpot RiType-implementations.
  */
 public abstract class HotSpotType extends CompilerObject implements RiType {
-    /**
-     * 
-     */
     private static final long serialVersionUID = -4252886265301910771L;
     protected String name;
 
@@ -44,4 +41,10 @@
     public final String name() {
         return name;
     }
+
+    /**
+     * Gets the object representing the C++ klassOop for this type.
+     * Such a value cannot be safely exposed to Java code.
+     */
+    public abstract HotSpotKlassOop klassOop();
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypePrimitive.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypePrimitive.java	Thu May 03 11:05:46 2012 +0200
@@ -35,17 +35,15 @@
  */
 public final class HotSpotTypePrimitive extends HotSpotType implements RiResolvedType {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = -6208552348908071473L;
     private CiKind kind;
-
+    private final HotSpotKlassOop klassOop;
 
     public HotSpotTypePrimitive(Compiler compiler, CiKind kind) {
         super(compiler);
         this.kind = kind;
         this.name = String.valueOf(Character.toUpperCase(kind.typeChar));
+        this.klassOop = new HotSpotKlassOop(compiler, kind.toJavaClass());
     }
 
     @Override
@@ -178,4 +176,9 @@
     public RiResolvedType resolve(RiResolvedType accessingClass) {
         return this;
     }
+
+    @Override
+    public HotSpotKlassOop klassOop() {
+        return klassOop;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolved.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolved.java	Thu May 03 11:05:46 2012 +0200
@@ -35,4 +35,5 @@
 
     RiField createRiField(String name, RiType type, int offset, int flags);
 
+    HotSpotKlassOop klassOop();
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolvedImpl.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolvedImpl.java	Thu May 03 11:05:46 2012 +0200
@@ -118,11 +118,9 @@
             case JavaClass:
                 return CiConstant.forObject(javaMirror);
             case ObjectHub:
-                return CiConstant.forObject(this);
+                return CiConstant.forObject(klassOop());
             case StaticFields:
                 return CiConstant.forObject(javaMirror);
-            case TypeInfo:
-                return CiConstant.forObject(this);
             default:
                 return null;
         }
@@ -220,7 +218,7 @@
 
         long id = offset + ((long) flags << 32);
 
-        // (thomaswue) Must cache the fields, because the local load elimination only works if the objects from two field lookups are equal.
+        // (thomaswue) Must cache the fields, because the local load elimination only works if the objects from two field lookups are identical.
         if (fieldCache == null) {
             fieldCache = new HashMap<>(8);
         } else {
@@ -265,4 +263,15 @@
     public RiResolvedType resolve(RiResolvedType accessingClass) {
         return this;
     }
+
+    // (dnsimon) this value may require identity semantics
+    private HotSpotKlassOop klassOopCache;
+
+    @Override
+    public synchronized HotSpotKlassOop klassOop() {
+        if (klassOopCache == null) {
+            klassOopCache = new HotSpotKlassOop(compiler, javaMirror);
+        }
+        return klassOopCache;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeUnresolved.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeUnresolved.java	Thu May 03 11:05:46 2012 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.Compiler;
 
 /**
@@ -119,4 +120,9 @@
     public RiResolvedType resolve(RiResolvedType accessingClass) {
         return (RiResolvedType) compiler.lookupType(name, (HotSpotTypeResolved) accessingClass, true);
     }
+
+    @Override
+    public HotSpotKlassOop klassOop() {
+        throw GraalInternalError.shouldNotReachHere("HotSpotTypeUnresolved.klassOop");
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java	Thu May 03 11:05:46 2012 +0200
@@ -25,9 +25,12 @@
 import static com.oracle.graal.hotspot.ri.TemplateFlag.*;
 import static com.oracle.max.cri.ci.CiValueUtil.*;
 
+import java.io.*;
 import java.util.*;
 import java.util.concurrent.*;
 
+import sun.misc.*;
+
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.Compiler;
@@ -288,7 +291,7 @@
         @Override
         protected XirTemplate create(CiXirAssembler asm, long flags, int size) {
             XirOperand result = asm.restart(target.wordKind);
-            XirOperand type = asm.createInputParameter("type", CiKind.Object);
+            XirOperand hub = asm.createInputParameter("hub", CiKind.Object);
 
             XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx);
             XirOperand temp1o = asm.createRegister("temp1o", CiKind.Object, AMD64.rcx);
@@ -299,7 +302,7 @@
             XirLabel resume = asm.createInlineLabel("resume");
 
             // check if the class is already initialized
-            asm.pload(CiKind.Int, temp2i, type, asm.i(config.klassStateOffset), false);
+            asm.pload(CiKind.Int, temp2i, hub, asm.i(config.klassStateOffset), false);
             asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized));
 
             XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15);
@@ -312,9 +315,9 @@
 
             asm.bindInline(resume);
 
-            asm.pload(target.wordKind, temp1, type, asm.i(config.instanceHeaderPrototypeOffset), false);
+            asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false);
             asm.pstore(target.wordKind, result, temp1, false);
-            asm.mov(temp1o, type); // need a temporary register since Intel cannot store 64-bit constants to memory
+            asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory
             asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), temp1o, false);
 
             if (size > 2 * target.wordSize) {
@@ -327,7 +330,7 @@
             // -- out of line -------------------------------------------------------
             asm.bindOutOfLine(tlabFull);
             XirOperand arg = asm.createRegisterTemp("runtime call argument", CiKind.Object, AMD64.rdx);
-            asm.mov(arg, type);
+            asm.mov(arg, hub);
             useRegisters(asm, AMD64.rax);
             asm.callRuntime(config.newInstanceStub, result);
             asm.jmp(resume);
@@ -460,56 +463,115 @@
         }
     };
 
+    enum CheckcastCounter {
+        hintsHit("hit a hint type"),
+        hintsMissed("missed the hint types"),
+        exact("tested type is (statically) final"),
+        noHints_class("profile information is not used (test type is a class)"),
+        noHints_iface("profile information is not used (test type is an interface)"),
+        noHints_unknown("test type is not a compile-time constant"),
+        isNull("object tested is null"),
+        exception("type test failed with a ClassCastException");
+
+        public final String desc;
+
+        private CheckcastCounter(String desc) {
+            this.desc = desc;
+        }
+
+        static final CheckcastCounter[] VALUES = values();
+    }
+
+    private static final long[] checkcastCounters = new long[CheckcastCounter.VALUES.length];
+
     private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) {
 
+        private void incCounter(CiXirAssembler asm, XirOperand counter, XirParameter counters, CheckcastCounter offset) {
+            int disp = Unsafe.getUnsafe().arrayBaseOffset(long[].class);
+            Scale scale = Scale.fromInt(Unsafe.getUnsafe().arrayIndexScale(long[].class));
+            XirConstant index = asm.i(offset.ordinal());
+            asm.pload(CiKind.Long, counter, counters, index, disp, scale, false);
+            asm.add(counter, counter, asm.i(1));
+            asm.pstore(CiKind.Long, counters, index, counter, disp, scale, false);
+        }
+
         @Override
         protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) {
             asm.restart(CiKind.Void);
+            boolean exact = is(EXACT_HINTS, flags);
+            XirParameter counters = GraalOptions.CheckcastCounters ? asm.createConstantInputParameter("counters", CiKind.Object) : null;
             XirParameter object = asm.createInputParameter("object", CiKind.Object);
-            final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", CiKind.Object);
+            final XirOperand hub = exact ? null : asm.createConstantInputParameter("hub", CiKind.Object);
 
             XirOperand objHub = asm.createTemp("objHub", CiKind.Object);
+            XirOperand counter = counters != null ? asm.createTemp("counter", CiKind.Long) : null;
 
-            XirLabel end = asm.createInlineLabel("end");
+            XirLabel success = asm.createInlineLabel("success");
             XirLabel slowPath = asm.createOutOfLineLabel("slow path");
 
             if (is(NULL_CHECK, flags)) {
                 // null can be cast to anything
-                asm.jeq(end, object, asm.o(null));
+                if (counters != null) {
+                    XirLabel isNotNull = asm.createInlineLabel("isNull");
+                    asm.jneq(isNotNull, object, asm.o(null));
+                    incCounter(asm, counter, counters, CheckcastCounter.isNull);
+                    asm.jmp(success);
+                    asm.bindInline(isNotNull);
+                } else {
+                    asm.jeq(success, object, asm.o(null));
+                }
+
             }
 
             asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false);
             if (hintCount == 0) {
-                assert !is(EXACT_HINTS, flags);
+                assert !exact;
+                if (counters != null) {
+                    incCounter(asm, counter, counters, is(NULL_TYPE, flags) ? CheckcastCounter.noHints_unknown : is(INTERFACE_TYPE, flags) ? CheckcastCounter.noHints_iface : CheckcastCounter.noHints_class);
+                }
+
                 checkSubtype(asm, objHub, objHub, hub);
                 asm.jeq(slowPath, objHub, asm.o(null));
-                asm.bindInline(end);
+                asm.bindInline(success);
 
                 // -- out of line -------------------------------------------------------
                 asm.bindOutOfLine(slowPath);
             } else {
+                XirLabel hintsSuccess = counters == null ? success : asm.createInlineLabel("hintsSuccess");
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
                 // if we get an exact match: succeed immediately
-                XirOperand hintHub = asm.createTemp("hintHub", CiKind.Object);
                 for (int i = 0; i < hintCount; i++) {
-                    XirParameter hintMirror = asm.createConstantInputParameter("hintMirror" + i, CiKind.Object);
-                    asm.pload(CiKind.Object, hintHub, hintMirror, asm.i(config.klassOopOffset), false);
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object);
+                    asm.mov(scratchObject, hintHub);
                     if (i < hintCount - 1) {
-                        asm.jeq(end, objHub, hintHub);
+                        asm.jeq(hintsSuccess, objHub, scratchObject);
                     } else {
-                        asm.jneq(slowPath, objHub, hintHub);
+                        asm.jneq(slowPath, objHub, scratchObject);
                     }
                 }
-                asm.bindInline(end);
+
+                if (counters != null) {
+                    asm.bindInline(hintsSuccess);
+                    incCounter(asm, counter, counters, exact ? CheckcastCounter.exact : CheckcastCounter.hintsHit);
+                }
+
+                asm.bindInline(success);
 
                 // -- out of line -------------------------------------------------------
                 asm.bindOutOfLine(slowPath);
-                if (!is(EXACT_HINTS, flags)) {
+                if (!exact) {
+                    if (counters != null) {
+                        incCounter(asm, counter, counters, CheckcastCounter.hintsMissed);
+                    }
                     checkSubtype(asm, objHub, objHub, hub);
-                    asm.jneq(end, objHub, asm.o(null));
+                    asm.jneq(success, objHub, asm.o(null));
                 }
             }
 
-            RiDeoptReason deoptReason = is(EXACT_HINTS, flags) ? RiDeoptReason.OptimizedTypeCheckViolated : RiDeoptReason.ClassCastException;
+            if (counters != null) {
+                incCounter(asm, counter, counters, CheckcastCounter.exception);
+            }
+            RiDeoptReason deoptReason = exact ? RiDeoptReason.OptimizedTypeCheckViolated : RiDeoptReason.ClassCastException;
             XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
             asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.InvalidateReprofile, deoptReason)));
             asm.callRuntime(CiRuntimeCall.Deoptimize, null);
@@ -545,21 +607,21 @@
                 asm.jmp(trueSucc);
             } else {
                 XirLabel slowPath = null;
-                XirOperand hintHub = asm.createTemp("hintHub", CiKind.Object);
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
 
                 // if we get an exact match: succeed immediately
                 for (int i = 0; i < hintCount; i++) {
-                    XirParameter hintMirror = asm.createConstantInputParameter("hintMirror" + i, CiKind.Object);
-                    asm.pload(CiKind.Object, hintHub, hintMirror, asm.i(config.klassOopOffset), false);
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object);
+                    asm.mov(scratchObject, hintHub);
                     if (i < hintCount - 1) {
-                        asm.jeq(trueSucc, objHub, hintHub);
+                        asm.jeq(trueSucc, objHub, scratchObject);
                     } else {
                         if (is(EXACT_HINTS, flags)) {
-                            asm.jneq(falseSucc, objHub, hintHub);
+                            asm.jneq(falseSucc, objHub, scratchObject);
                             asm.jmp(trueSucc);
                         } else {
                             slowPath = asm.createOutOfLineLabel("slow path");
-                            asm.jneq(slowPath, objHub, hintHub);
+                            asm.jneq(slowPath, objHub, scratchObject);
                             asm.jmp(trueSucc);
                         }
                     }
@@ -610,20 +672,20 @@
                 asm.bindInline(end);
             } else {
                 XirLabel slowPath = null;
-                XirOperand hintHub = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
 
                 // if we get an exact match: succeed immediately
                 for (int i = 0; i < hintCount; i++) {
-                    XirParameter hintMirror = asm.createConstantInputParameter("hintMirror" + i, CiKind.Object);
-                    asm.pload(CiKind.Object, hintHub, hintMirror, asm.i(config.klassOopOffset), false);
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object);
+                    asm.mov(scratchObject, hintHub);
                     if (i < hintCount - 1) {
-                        asm.jeq(end, objHub, hintHub);
+                        asm.jeq(end, objHub, scratchObject);
                     } else {
                         if (is(EXACT_HINTS, flags)) {
-                            asm.jeq(end, objHub, hintHub);
+                            asm.jeq(end, objHub, scratchObject);
                         } else {
                             slowPath = asm.createOutOfLineLabel("slow path");
-                            asm.jeq(end, objHub, hintHub);
+                            asm.jeq(end, objHub, scratchObject);
                             asm.jmp(slowPath);
                         }
                     }
@@ -645,166 +707,6 @@
         }
     };
 
-    private KindTemplates arrayCopyTemplates = new KindTemplates() {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
-            asm.restart(CiKind.Void);
-            XirParameter src = asm.createInputParameter("src", CiKind.Object);
-            XirParameter srcPos = asm.createInputParameter("srcPos", CiKind.Int, true);
-            XirParameter dest = asm.createInputParameter("dest", CiKind.Object);
-            XirParameter destPos = asm.createInputParameter("destPos", CiKind.Int, true);
-            XirParameter length = asm.createInputParameter("length", CiKind.Int, true);
-
-            XirOperand tempSrc = asm.createTemp("tempSrc", target.wordKind);
-            XirOperand tempDest = asm.createTemp("tempDest", target.wordKind);
-            XirOperand lengthOperand = asm.createRegisterTemp("lengthOperand", CiKind.Int, AMD64.rax);
-
-            XirOperand compHub = null;
-            XirOperand valueHub = null;
-            XirOperand temp = null;
-            XirLabel store = null;
-            XirLabel slowStoreCheck = null;
-
-            if (is(STORE_CHECK, flags) && kind == CiKind.Object) {
-                valueHub = asm.createRegisterTemp("valueHub", target.wordKind, AMD64.rdi);
-                compHub = asm.createRegisterTemp("compHub", target.wordKind, AMD64.rsi);
-                temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.r10);
-            }
-
-            // Calculate the factor for the repeat move instruction.
-            int elementSize = target.sizeInBytes(kind);
-            int factor;
-            boolean wordSize;
-            if (elementSize >= target.wordSize) {
-                assert elementSize % target.wordSize == 0;
-                wordSize = true;
-                factor = elementSize / target.wordSize;
-            } else {
-                factor = elementSize;
-                wordSize = false;
-            }
-
-            // Adjust the length if the factor is not 1.
-            if (factor != 1) {
-                asm.shl(lengthOperand, length, asm.i(CiUtil.log2(factor)));
-            } else {
-                asm.mov(lengthOperand, length);
-            }
-
-            // Set the start and the end pointer.
-            asm.lea(tempSrc, src, srcPos, config.getArrayOffset(kind), Scale.fromInt(elementSize));
-            asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize));
-
-            XirLabel reverse = null;
-            XirLabel normal = null;
-
-            if (is(STORE_CHECK, flags)) {
-                reverse = asm.createInlineLabel("reverse");
-                asm.jneq(reverse, src, dest);
-            }
-
-            if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) {
-                normal = asm.createInlineLabel("normal");
-                asm.jneq(normal, src, dest);
-            }
-
-            if (!is(INPUTS_DIFFERENT, flags)) {
-                if (reverse == null) {
-                    reverse = asm.createInlineLabel("reverse");
-                }
-                asm.jlt(reverse, srcPos, destPos);
-            }
-
-            if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) {
-                asm.bindInline(normal);
-            }
-
-            // Everything set up => repeat mov.
-            if (wordSize) {
-                asm.repmov(tempSrc, tempDest, lengthOperand);
-            } else {
-                asm.repmovb(tempSrc, tempDest, lengthOperand);
-            }
-
-            if (!is(INPUTS_DIFFERENT, flags) || is(STORE_CHECK, flags)) {
-
-                XirLabel end = asm.createInlineLabel("end");
-                asm.jmp(end);
-
-                // Implement reverse copy, because srcPos < destPos and src == dest.
-                asm.bindInline(reverse);
-
-                if (is(STORE_CHECK, flags)) {
-                    asm.pload(CiKind.Object, compHub, dest, asm.i(config.hubOffset), false);
-                    asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false);
-                }
-
-                CiKind copyKind = wordSize ? CiKind.Object : CiKind.Byte;
-                XirOperand tempValue = asm.createTemp("tempValue", copyKind);
-                XirLabel start = asm.createInlineLabel("start");
-                asm.bindInline(start);
-                asm.sub(lengthOperand, lengthOperand, asm.i(1));
-                asm.jlt(end, lengthOperand, asm.i(0));
-
-                Scale scale = wordSize ? Scale.fromInt(target.wordSize) : Scale.Times1;
-                asm.pload(copyKind, tempValue, tempSrc, lengthOperand, 0, scale, false);
-
-                if (is(STORE_CHECK, flags)) {
-                    slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck");
-                    store = asm.createInlineLabel("store");
-                    asm.jeq(store, tempValue, asm.o(null)); // first check if value is null
-                    asm.pload(CiKind.Object, valueHub, tempValue, asm.i(config.hubOffset), false);
-                    asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub
-                    asm.bindInline(store);
-                }
-
-                asm.pstore(copyKind, tempDest, lengthOperand, tempValue, 0, scale, false);
-
-                asm.jmp(start);
-                asm.bindInline(end);
-            }
-
-            if (kind == CiKind.Object) {
-                // Do write barriers
-                asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize));
-                asm.shr(tempDest, tempDest, asm.i(config.cardtableShift));
-                asm.pstore(CiKind.Boolean, wordConst(asm, config.cardtableStartAddress), tempDest, asm.b(false), false);
-
-                XirOperand tempDestEnd = tempSrc; // Reuse src temp
-                asm.lea(tempDestEnd, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize));
-                asm.add(tempDestEnd, tempDestEnd, length);
-                asm.shr(tempDestEnd, tempDestEnd, asm.i(config.cardtableShift));
-
-                // Jump to out-of-line write barrier loop if the array is big.
-                XirLabel writeBarrierLoop = asm.createOutOfLineLabel("writeBarrierLoop");
-                asm.jneq(writeBarrierLoop, tempDest, tempSrc);
-                XirLabel back = asm.createInlineLabel("back");
-                asm.bindInline(back);
-
-                asm.bindOutOfLine(writeBarrierLoop);
-                asm.pstore(CiKind.Boolean, wordConst(asm, config.cardtableStartAddress), tempDestEnd, asm.b(false), false);
-                asm.sub(tempDestEnd, tempDestEnd, asm.i(1));
-                asm.jneq(writeBarrierLoop, tempDestEnd, tempDest);
-                asm.jmp(back);
-            }
-
-            if (is(STORE_CHECK, flags)) {
-                assert kind == CiKind.Object;
-                useRegisters(asm, AMD64.rax);
-                asm.bindOutOfLine(slowStoreCheck);
-                checkSubtype(asm, temp, valueHub, compHub);
-                asm.jneq(store, temp, wordConst(asm, 0));
-                XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
-                asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.None, RiDeoptReason.ClassCastException)));
-                asm.callRuntime(CiRuntimeCall.Deoptimize, null);
-                asm.jmp(store);
-            }
-
-            return asm.finishTemplate("arraycopy<" + kind + ">");
-        }
-    };
-
     private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) {
        @Override
        protected XirTemplate create(CiXirAssembler asm, long flags) {
@@ -871,43 +773,57 @@
 
     @Override
     public XirSnippet genNewInstance(XirSite site, RiType type) {
-        int instanceSize = ((HotSpotTypeResolved) type).instanceSize();
-        return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(type));
+        HotSpotTypeResolved resolvedType = (HotSpotTypeResolved) type;
+        int instanceSize = resolvedType.instanceSize();
+        return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(resolvedType.klassOop()));
     }
 
     @Override
     public XirSnippet genNewArray(XirSite site, XirArgument length, CiKind elementKind, RiType componentType, RiType arrayType) {
         if (elementKind == CiKind.Object) {
             assert arrayType instanceof RiResolvedType;
-            return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(arrayType));
+            return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(((HotSpotType) arrayType).klassOop()));
         } else {
             assert arrayType == null;
             RiType primitiveArrayType = compiler.getCompilerToVM().getPrimitiveArrayType(elementKind);
-            return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(primitiveArrayType));
+            return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(((HotSpotType) primitiveArrayType).klassOop()));
         }
     }
 
     @Override
     public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type) {
         XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1);
-        params[lengths.length] = XirArgument.forObject(type);
+        params[lengths.length] = XirArgument.forObject(((HotSpotType) type).klassOop());
         return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params);
     }
 
     @Override
-    public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact) {
+    public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiResolvedType type, RiResolvedType[] hints, boolean hintsExact) {
+        final boolean useCounters = GraalOptions.CheckcastCounters;
         if (hints == null || hints.length == 0) {
-            return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub);
+            if (useCounters) {
+                if (type == null) {
+                    return new XirSnippet(checkCastTemplates.get(site, 0, NULL_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub);
+                } else if (type.isInterface()) {
+                    return new XirSnippet(checkCastTemplates.get(site, 0, INTERFACE_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub);
+                } else {
+                    return new XirSnippet(checkCastTemplates.get(site, 0), XirArgument.forObject(checkcastCounters), receiver, hub);
+                }
+            } else {
+                return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub);
+            }
         } else {
-            XirArgument[] params = new XirArgument[hints.length + (hintsExact ? 1 : 2)];
+            XirArgument[] params = new XirArgument[(useCounters ? 1 : 0) + hints.length + (hintsExact ? 1 : 2)];
             int i = 0;
+            if (useCounters) {
+                params[i++] = XirArgument.forObject(checkcastCounters);
+            }
             params[i++] = receiver;
             if (!hintsExact) {
                 params[i++] = hub;
             }
             for (RiResolvedType hint : hints) {
-                Object hintMirror = hint.toJava();
-                params[i++] = XirArgument.forObject(hintMirror);
+                params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop());
             }
             XirTemplate template = hintsExact ? checkCastTemplates.get(site, hints.length, EXACT_HINTS) : checkCastTemplates.get(site, hints.length);
             return new XirSnippet(template, params);
@@ -926,8 +842,7 @@
                 params[i++] = hub;
             }
             for (RiResolvedType hint : hints) {
-                Object hintMirror = hint.toJava();
-                params[i++] = XirArgument.forObject(hintMirror);
+                params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop());
             }
             XirTemplate template = hintsExact ? instanceOfTemplates.get(site, hints.length, EXACT_HINTS) : instanceOfTemplates.get(site, hints.length);
             return new XirSnippet(template, params);
@@ -948,8 +863,7 @@
             params[i++] = trueValue;
             params[i++] = falseValue;
             for (RiResolvedType hint : hints) {
-                Object hintMirror = hint.toJava();
-                params[i++] = XirArgument.forObject(hintMirror);
+                params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop());
             }
             XirTemplate template = hintsExact ? materializeInstanceOfTemplates.get(site, hints.length, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hints.length);
             return new XirSnippet(template, params);
@@ -957,23 +871,6 @@
     }
 
     @Override
-    public XirSnippet genArrayCopy(XirSite site, XirArgument src, XirArgument srcPos, XirArgument dest, XirArgument destPos, XirArgument length, RiType elementType, boolean inputsSame, boolean inputsDifferent) {
-        if (elementType == null) {
-            return null;
-        }
-        assert !inputsDifferent || !inputsSame;
-        XirTemplate template = null;
-        if (inputsDifferent) {
-            template = arrayCopyTemplates.get(site, elementType.kind(true), INPUTS_DIFFERENT);
-        } else if (inputsSame) {
-            template = arrayCopyTemplates.get(site, elementType.kind(true), INPUTS_SAME);
-        } else {
-            template = arrayCopyTemplates.get(site, elementType.kind(true));
-        }
-        return new XirSnippet(template, src, srcPos, dest, destPos, length);
-    }
-
-    @Override
     public XirSnippet genTypeBranch(XirSite site, XirArgument thisHub, XirArgument otherHub, RiType type) {
         assert type instanceof RiResolvedType;
         return new XirSnippet(typeCheckTemplates.get(site), thisHub, otherHub);
@@ -1096,4 +993,43 @@
             return getInternal(getBits(kind.ordinal(), site, flags));
         }
     }
+
+    private static void printCounter(PrintStream out, CheckcastCounter name, long count, long total) {
+        double percent = ((double) (count * 100)) / total;
+        out.println(String.format("%16s: %5.2f%%%10d  // %s", name, percent, count, name.desc));
+    }
+
+    public static  void printCheckcastCounters(PrintStream out) {
+        class Count implements Comparable<Count> {
+            long c;
+            CheckcastCounter name;
+            Count(long c, CheckcastCounter name) {
+                this.c = c;
+                this.name = name;
+            }
+            public int compareTo(Count o) {
+                return (int) (o.c - c);
+            }
+        }
+
+        long total = 0;
+        Count[] counters = new Count[checkcastCounters.length];
+        for (int i = 0; i < counters.length; i++) {
+            counters[i] = new Count(checkcastCounters[i], CheckcastCounter.VALUES[i]);
+            total += checkcastCounters[i];
+        }
+        Arrays.sort(counters);
+
+        out.println();
+        out.println("** Checkcast counters **");
+        for (Count c : counters) {
+            printCounter(out, c.name, c.c, total);
+        }
+    }
+
+    public static void printCounters(PrintStream out) {
+        if (GraalOptions.CheckcastCounters) {
+            printCheckcastCounters(out);
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/TemplateFlag.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/TemplateFlag.java	Thu May 03 11:05:46 2012 +0200
@@ -23,7 +23,19 @@
 package com.oracle.graal.hotspot.ri;
 
 enum TemplateFlag {
-    NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED, EXACT_HINTS;
+    NULL_CHECK,
+    READ_BARRIER,
+    WRITE_BARRIER,
+    STORE_CHECK,
+    BOUNDS_CHECK,
+    GIVEN_LENGTH,
+    INPUTS_DIFFERENT,
+    INPUTS_SAME,
+    STATIC_METHOD,
+    SYNCHRONIZED,
+    INTERFACE_TYPE,
+    NULL_TYPE,
+    EXACT_HINTS;
 
     private static final long FIRST_FLAG = 0x0000000100000000L;
     public static final long FLAGS_MASK = 0x0000FFFF00000000L;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/server/ReplacingStreams.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/server/ReplacingStreams.java	Thu May 03 11:05:46 2012 +0200
@@ -74,9 +74,6 @@
 
     public static class Placeholder implements Serializable {
 
-        /**
-         *
-         */
         private static final long serialVersionUID = 6071894297788156945L;
         public final int id;
 
@@ -92,9 +89,6 @@
 
     public static class NewRemoteCallPlaceholder implements Serializable {
 
-        /**
-         *
-         */
         private static final long serialVersionUID = 3084101671389500206L;
         public final Class<?>[] interfaces;
 
@@ -104,10 +98,6 @@
     }
 
     public static class NewDummyPlaceholder implements Serializable {
-
-        /**
-         *
-         */
         private static final long serialVersionUID = 2692666726573532288L;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Thu May 03 11:05:46 2012 +0200
@@ -35,6 +35,7 @@
 import com.oracle.graal.compiler.target.amd64.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.counters.*;
 import com.oracle.graal.hotspot.ri.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
@@ -75,6 +76,12 @@
                 emitStore(pcAddress, CiConstant.LONG_0, false);
                 setResult(x, exception);
             }
+
+            @Override
+            protected void emitPrologue() {
+                super.emitPrologue();
+                MethodEntryCounters.emitCounter(this, method);
+            }
         };
     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu May 03 11:05:46 2012 +0200
@@ -46,6 +46,7 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.cri.ri.RiType.Representation;
+import com.oracle.max.cri.ri.RiTypeProfile.ProfiledType;
 import com.oracle.max.criutils.*;
 
 /**
@@ -146,7 +147,8 @@
         }
 
         if (GraalOptions.PrintProfilingInformation) {
-            method.dumpProfile();
+            TTY.println("Profiling info for " + method);
+            TTY.println(CiUtil.indent(CiUtil.profileAsString(method), "  "));
         }
 
         // compute the block map, setup exception handlers and get the entrypoint(s)
@@ -591,7 +593,7 @@
     private static final RiResolvedType[] EMPTY_TYPE_ARRAY = new RiResolvedType[0];
 
     private RiResolvedType[] getTypeCheckHints(RiResolvedType type, int maxHints) {
-        if (!optimisticOpts.useUseTypeCheckHints() || Util.isFinalClass(type)) {
+        if (!optimisticOpts.useTypeCheckHints() || Util.isFinalClass(type)) {
             return new RiResolvedType[] {type};
         } else {
             RiResolvedType uniqueSubtype = type.uniqueConcreteSubtype();
@@ -601,17 +603,24 @@
                 RiTypeProfile typeProfile = profilingInfo.getTypeProfile(bci());
                 if (typeProfile != null) {
                     double notRecordedTypes = typeProfile.getNotRecordedProbability();
-                    RiResolvedType[] types = typeProfile.getTypes();
-
-                    if (notRecordedTypes == 0 && types != null && types.length > 0 && types.length <= maxHints) {
-                        RiResolvedType[] hints = new RiResolvedType[types.length];
+                    ProfiledType[] ptypes = typeProfile.getTypes();
+                    if (notRecordedTypes < (1D - GraalOptions.CheckcastMinHintHitProbability) && ptypes != null && ptypes.length > 0) {
+                        RiResolvedType[] hints = new RiResolvedType[ptypes.length];
                         int hintCount = 0;
-                        for (RiResolvedType hint : types) {
+                        double totalHintProbability = 0.0d;
+                        for (ProfiledType ptype : ptypes) {
+                            RiResolvedType hint = ptype.type;
                             if (hint.isSubtypeOf(type)) {
                                 hints[hintCount++] = hint;
+                                totalHintProbability += ptype.probability;
                             }
                         }
-                        return Arrays.copyOf(hints, Math.min(maxHints, hintCount));
+                        if (totalHintProbability >= GraalOptions.CheckcastMinHintHitProbability) {
+                            if (hints.length == hintCount && hintCount <= maxHints) {
+                                return hints;
+                            }
+                            return Arrays.copyOf(hints, Math.min(maxHints, hintCount));
+                        }
                     }
                 }
                 return EMPTY_TYPE_ARRAY;
@@ -629,7 +638,7 @@
             AnchorNode anchor = currentGraph.add(new AnchorNode());
             append(anchor);
             CheckCastNode checkCast;
-            RiResolvedType[] hints = getTypeCheckHints((RiResolvedType) type, 2);
+            RiResolvedType[] hints = getTypeCheckHints((RiResolvedType) type, GraalOptions.CheckcastMaxHints);
             checkCast = currentGraph.unique(new CheckCastNode(anchor, typeInstruction, (RiResolvedType) type, object, hints, Util.isFinalClass((RiResolvedType) type)));
             append(currentGraph.add(new ValueAnchorNode(checkCast)));
             frameState.apush(checkCast);
@@ -648,7 +657,7 @@
             RiResolvedType resolvedType = (RiResolvedType) type;
             ConstantNode hub = appendConstant(resolvedType.getEncoding(RiType.Representation.ObjectHub));
 
-            RiResolvedType[] hints = getTypeCheckHints(resolvedType, 1);
+            RiResolvedType[] hints = getTypeCheckHints(resolvedType, GraalOptions.InstanceOfMaxHints);
             InstanceOfNode instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, hints, Util.isFinalClass(resolvedType), false);
             frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph)));
         } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Thu May 03 11:05:46 2012 +0200
@@ -30,17 +30,17 @@
 public class PiNode extends FloatingNode implements LIRLowerable {
 
     @Input private ValueNode object;
-    @Input private BeginNode anchor;
+    @Input(notDataflow = true) private final FixedNode anchor;
 
     public ValueNode object() {
         return object;
     }
 
-    public BeginNode anchor() {
+    public FixedNode anchor() {
         return anchor;
     }
 
-    public PiNode(ValueNode object, BeginNode anchor, Stamp stamp) {
+    public PiNode(ValueNode object, FixedNode anchor, Stamp stamp) {
         super(stamp);
         this.object = object;
         this.anchor = anchor;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Thu May 03 11:05:46 2012 +0200
@@ -73,6 +73,27 @@
         this(null, method);
     }
 
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder(getClass().getSimpleName() + ":" + graphId);
+        String sep = "{";
+        if (name != null) {
+            buf.append(sep);
+            buf.append(name);
+            sep = ", ";
+        }
+        if (method != null) {
+            buf.append(sep);
+            buf.append(method);
+            sep = ", ";
+        }
+
+        if (!sep.equals("{")) {
+            buf.append("}");
+        }
+        return buf.toString();
+    }
+
     public BeginNode start() {
         return start;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Thu May 03 11:05:46 2012 +0200
@@ -46,6 +46,6 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitCallToRuntime(CiRuntimeCall.UnwindException, false, gen.operand(exception()));
+        gen.emitCall(CiRuntimeCall.UnwindException, false, gen.operand(exception()));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NullCheckNode.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NullCheckNode.java	Thu May 03 11:05:46 2012 +0200
@@ -28,6 +28,10 @@
 import com.oracle.graal.nodes.spi.types.*;
 import com.oracle.graal.nodes.type.*;
 
+/**
+ * A NullCheckNode will be true if the supplied value is non-null, and false if it is null.
+ * This behavior can be inverted by setting {@link #expectedNull} to true.
+ */
 public final class NullCheckNode extends BooleanNode implements Canonicalizable, LIRLowerable, ConditionalTypeFeedbackProvider, TypeCanonicalizable {
 
     @Input private ValueNode object;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Thu May 03 11:05:46 2012 +0200
@@ -40,16 +40,11 @@
 public final class CheckCastNode extends TypeCheckNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType, TypeFeedbackProvider, TypeCanonicalizable {
 
     @Input(notDataflow = true) protected final FixedNode anchor;
-    protected final boolean emitCode;
 
     public FixedNode anchor() {
         return anchor;
     }
 
-    public boolean emitCode() {
-        return emitCode;
-    }
-
     /**
      * Creates a new CheckCast instruction.
      *
@@ -61,18 +56,9 @@
         this(anchor, targetClassInstruction, targetClass, object, EMPTY_HINTS, false);
     }
 
-    public CheckCastNode(FixedNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, boolean emitCode) {
-        this(anchor, targetClassInstruction, targetClass, object, EMPTY_HINTS, false, emitCode);
-    }
-
     public CheckCastNode(FixedNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact) {
-        this(anchor, targetClassInstruction, targetClass, object, hints, hintsExact, true);
-    }
-
-    private CheckCastNode(FixedNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact, boolean emitCode) {
         super(targetClassInstruction, targetClass, object, hints, hintsExact, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass));
         this.anchor = anchor;
-        this.emitCode = emitCode;
     }
 
     @Override
@@ -82,12 +68,16 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
+        assert object() != null : this;
+
         RiResolvedType objectDeclaredType = object().declaredType();
         RiResolvedType targetClass = targetClass();
         if (objectDeclaredType != null && targetClass != null && objectDeclaredType.isSubtypeOf(targetClass)) {
+            // we don't have to check for null types here because they will also pass the checkcast.
             freeAnchor();
             return object();
         }
+
         CiConstant constant = object().asConstant();
         if (constant != null) {
             assert constant.kind == CiKind.Object;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Thu May 03 11:05:46 2012 +0200
@@ -22,14 +22,13 @@
  */
 package com.oracle.graal.nodes.java;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.graal.graph.Node.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.types.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
 
 /**
  * The {@code InstanceOfNode} represents an instanceof test.
@@ -66,17 +65,44 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         assert object() != null : this;
+
         RiResolvedType exact = object().exactType();
         if (exact != null) {
-            boolean result = exact.isSubtypeOf(targetClass());
-            if (result != negated) {
-                // The instanceof check reduces to a null check.
-                return graph().unique(new NullCheckNode(object(), false));
+            boolean subType = exact.isSubtypeOf(targetClass());
+
+            if (subType) {
+                if (object().stamp().nonNull()) {
+                    // the instanceOf matches, so return true (or false, for the negated case)
+                    return ConstantNode.forBoolean(!negated, graph());
+                } else {
+                    // the instanceof matches if the object is non-null, so return true (or false, for the negated case) depending on the null-ness.
+                    return graph().unique(new NullCheckNode(object(), negated));
+                }
             } else {
-                // The instanceof check can never succeed.
-                return ConstantNode.forBoolean(false, graph());
+                // since this type check failed for an exact type we know that it can never succeed at run time.
+                // we also don't care about null values, since they will also make the check fail.
+                // so return false (or true, for the negated case)
+                return ConstantNode.forBoolean(negated, graph());
+            }
+        } else {
+            RiResolvedType declared = object().declaredType();
+            if (declared != null) {
+                boolean subType = declared.isSubtypeOf(targetClass());
+
+                if (subType) {
+                    if (object().stamp().nonNull()) {
+                        // the instanceOf matches, so return true (or false, for the negated case)
+                        return ConstantNode.forBoolean(!negated, graph());
+                    } else {
+                        // the instanceof matches if the object is non-null, so return true (or false, for the negated case) depending on the null-ness.
+                        return graph().unique(new NullCheckNode(object(), negated));
+                    }
+                } else {
+                    // since the subtype comparison was only performed on a declared type we don't really know if it might be true at run time...
+                }
             }
         }
+
         CiConstant constant = object().asConstant();
         if (constant != null) {
             assert constant.kind == CiKind.Object;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Thu May 03 11:05:46 2012 +0200
@@ -46,7 +46,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitCallToRuntime(CiRuntimeCall.RegisterFinalizer, true, gen.operand(object()));
+        gen.emitCall(CiRuntimeCall.RegisterFinalizer, true, gen.operand(object()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu May 03 11:05:46 2012 +0200
@@ -81,7 +81,10 @@
     public abstract void emitMembar(int barriers);
     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 CiValue emitCall(Object target, CiKind result, CiKind[] arguments, boolean canTrap, CiValue... args);
+    public final CiValue emitCall(CiRuntimeCall runtimeCall, boolean canTrap, CiValue... args) {
+        return emitCall(runtimeCall, runtimeCall.resultKind, runtimeCall.arguments, canTrap, args);
+    }
 
     public abstract void emitIf(IfNode i);
     public abstract void emitConditional(ConditionalNode i);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Thu May 03 11:05:46 2012 +0200
@@ -232,7 +232,7 @@
     public static Stamp declared(final RiResolvedType type) {
         assert type != null;
         assert type.kind(false) == CiKind.Object;
-        return new BasicValueStamp(CiKind.Object, false, type, null);
+        return new BasicValueStamp(CiKind.Object, false, type, type.exactType());
     }
 
     public static Stamp declaredNonNull(final RiResolvedType type) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSnippets.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSnippets.java	Thu May 03 11:05:46 2012 +0200
@@ -27,13 +27,16 @@
 import com.oracle.graal.nodes.extended.*;
 
 /**
- * Snippets for {@link NodeClass} methods.
+ * Snippets for improving the performance of some critical methods in {@link NodeClass} methods.
+ * These snippets improve the performance by forcing the relevant methods to be inlined
+ * (intrinsification being a special form of inlining) and removing a checked cast.
+ * The latter cannot be done directly in Java code as {@link UnsafeCastNode}
+ * is not available to the project containing {@link NodeClass}.
  */
 @SuppressWarnings("unused")
 @ClassSubstitution(NodeClass.class)
 public class NodeClassSnippets implements SnippetsInterface {
 
-
     private static Node getNode(Node node, long offset) {
         return UnsafeCastNode.cast(UnsafeLoadNode.load(node, 0, offset, CiKind.Object), Node.class);
     }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java	Thu May 03 11:05:46 2012 +0200
@@ -24,8 +24,8 @@
 
 import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.graal.compiler.target.amd64.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Reg;
@@ -34,8 +34,9 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.snippets.target.amd64.*;
+import com.oracle.max.cri.ci.*;
 
-public class MathIntrinsicNode extends FloatingNode implements Canonicalizable, AMD64LIRLowerable {
+public class MathIntrinsicNode extends FloatingNode implements Canonicalizable, LIRGenLowerable {
 
     @Input private ValueNode x;
     private final Operation operation;
@@ -60,7 +61,7 @@
     }
 
     @Override
-    public void generateAmd64(AMD64LIRGenerator gen) {
+    public void generate(LIRGenerator gen) {
         Variable input = gen.load(gen.operand(x()));
         Variable result = gen.newVariable(kind());
         switch (operation()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InstanceOfCanonicalizerTest.java	Thu May 03 11:05:46 2012 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.tests;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+
+public class InstanceOfCanonicalizerTest extends GraphTest {
+
+    /**
+     * The problem tested here is the following: When canonicalizing a negated instanceof for which the exact type
+     * suggests that the instanceof is true, we still need to check if the value is null. (because this would make the
+     * instanceof false, and thus the negated instanceof true).
+     *
+     * This test case is constructed by replacing an instanceof with its negated counterpart, since negated instanceof
+     * operations will only be created in complicated cases.
+     */
+    @Test
+    public void test1() {
+        StructuredGraph graph = parse("testSnippet1");
+        Debug.dump(graph, "Graph");
+        for (Node node : graph.getNodes().snapshot()) {
+            if (node instanceof InstanceOfNode) {
+                graph.replaceFloating((InstanceOfNode) node, ((InstanceOfNode) node).negate());
+            }
+        }
+        new CanonicalizerPhase(null, runtime(), null).apply(graph);
+        Debug.dump(graph, "Graph");
+        for (Node node : graph.getNodes()) {
+            if (node instanceof InstanceOfNode) {
+                Assert.fail("InstanceOfNode should have been canonicalized");
+            } else if (node instanceof ReturnNode) {
+                ReturnNode ret = (ReturnNode) node;
+                Assert.assertTrue("return value should be a MaterializeNode " + ret.result(), ret.result() instanceof MaterializeNode);
+                MaterializeNode materialize = (MaterializeNode) ret.result();
+                Assert.assertTrue("return value should depend on nullness of parameter " + materialize.condition(), materialize.condition() instanceof NullCheckNode);
+            }
+
+        }
+    }
+
+    @SuppressWarnings("all")
+    public static boolean testSnippet1(String s) {
+        return s instanceof String;
+    }
+}
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiDebugInfo.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiDebugInfo.java	Thu May 03 11:05:46 2012 +0200
@@ -30,9 +30,6 @@
  */
 public class CiDebugInfo implements Serializable {
 
-    /**
-     * 
-     */
     private static final long serialVersionUID = -6047206624915812516L;
 
     /**
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiRegister.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiRegister.java	Thu May 03 11:05:46 2012 +0200
@@ -30,9 +30,6 @@
  */
 public final class CiRegister implements Comparable<CiRegister>, Serializable {
 
-    /**
-     * 
-     */
     private static final long serialVersionUID = -7213269157816016300L;
 
     /**
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiTargetMethod.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiTargetMethod.java	Thu May 03 11:05:46 2012 +0200
@@ -34,18 +34,12 @@
  */
 public class CiTargetMethod implements Serializable {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = -1319947729753702434L;
 
     /**
      * Represents a code position with associated additional information.
      */
     public abstract static class Site implements Serializable {
-        /**
-         *
-         */
         private static final long serialVersionUID = -8214214947651979102L;
         /**
          * The position (or offset) of this site with respect to the start of the target method.
@@ -61,9 +55,6 @@
      * Represents a safepoint with associated debug info.
      */
     public static class Safepoint extends Site implements Comparable<Safepoint> {
-        /**
-         *
-         */
         private static final long serialVersionUID = 2479806696381720162L;
         public final CiDebugInfo debugInfo;
 
@@ -96,9 +87,6 @@
      * Represents a call in the code.
      */
     public static final class Call extends Safepoint {
-        /**
-         *
-         */
         private static final long serialVersionUID = 1440741241631046954L;
 
         /**
@@ -145,9 +133,6 @@
      * Represents a reference to data from the code. The associated data can be any constant.
      */
     public static final class DataPatch extends Site {
-        /**
-         *
-         */
         private static final long serialVersionUID = 5771730331604867476L;
         public final CiConstant constant;
         public final int alignment;
@@ -169,9 +154,6 @@
      * This is optional information that can be used to enhance a disassembly of the code.
      */
     public abstract static class CodeAnnotation implements Serializable {
-        /**
-         *
-         */
         private static final long serialVersionUID = -7903959680749520748L;
         public final int position;
 
@@ -204,9 +186,6 @@
      * Labels some inline data in the code.
      */
     public static final class InlineData extends CodeAnnotation {
-        /**
-         *
-         */
         private static final long serialVersionUID = 305997507263827108L;
         public final int size;
         public InlineData(int position, int size) {
@@ -228,9 +207,6 @@
      * The table is indexed by the contiguous range of integers from {@link #low} to {@link #high} inclusive.
      */
     public static final class JumpTable extends CodeAnnotation {
-        /**
-         *
-         */
         private static final long serialVersionUID = 2222194398353801831L;
 
         /**
@@ -267,9 +243,6 @@
      * based on a key value from a sparse value set (e.g. the {@code lookupswitch} JVM instruction).
      */
     public static final class LookupTable extends CodeAnnotation {
-        /**
-         *
-         */
         private static final long serialVersionUID = 8367952567559116160L;
 
         /**
@@ -305,9 +278,6 @@
      * well as the caught exception type.
      */
     public static final class ExceptionHandler extends Site {
-        /**
-         *
-         */
         private static final long serialVersionUID = 4897339464722665281L;
         public final int handlerPos;
 
@@ -323,9 +293,6 @@
     }
 
     public static final class Mark extends Site {
-        /**
-         *
-         */
         private static final long serialVersionUID = 3612943150662354844L;
         public final Object id;
         public final Mark[] references;
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiUtil.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiUtil.java	Thu May 03 11:05:46 2012 +0200
@@ -28,6 +28,7 @@
 import java.util.*;
 
 import com.oracle.max.cri.ri.*;
+import com.oracle.max.cri.ri.RiTypeProfile.ProfiledType;
 
 /**
  * Miscellaneous collection of utility methods used in the {@code CRI} project.
@@ -736,4 +737,64 @@
         }
         return result;
     }
+
+    /**
+     * Formats the profiling information associated with a given method to a string.
+     */
+    public static String profileAsString(RiResolvedMethod method) {
+        StringBuilder buf = new StringBuilder(100);
+        buf.append(String.format("canBeStaticallyBound: %b%n", method.canBeStaticallyBound())).
+            append(String.format("invocationCount: %d%n", method.invocationCount()));
+        RiProfilingInfo profilingInfo = method.profilingInfo();
+        if (profilingInfo != null) {
+            for (int i = 0; i < method.codeSize(); i++) {
+                if (profilingInfo.getExecutionCount(i) != -1) {
+                    buf.append(String.format("executionCount@%d: %d%n", i, profilingInfo.getExecutionCount(i)));
+                }
+
+                if (profilingInfo.getBranchTakenProbability(i) != -1) {
+                    buf.append(String.format("branchProbability@%d: %.3f%n", i, profilingInfo.getBranchTakenProbability(i)));
+                }
+
+                double[] switchProbabilities = profilingInfo.getSwitchProbabilities(i);
+                if (switchProbabilities != null) {
+                    buf.append(String.format("switchProbabilities@%d:", i));
+                    for (int j = 0; j < switchProbabilities.length; j++) {
+                        buf.append(String.format(" %.3f", switchProbabilities[j]));
+                    }
+                    buf.append(NEW_LINE);
+                }
+
+                if (profilingInfo.getExceptionSeen(i) != RiExceptionSeen.FALSE) {
+                    buf.append(String.format("exceptionSeen@%d: %s%n", i, profilingInfo.getExceptionSeen(i).name()));
+                }
+
+                RiTypeProfile typeProfile = profilingInfo.getTypeProfile(i);
+                if (typeProfile != null) {
+                    ProfiledType[] ptypes = typeProfile.getTypes();
+                    if (ptypes != null) {
+                        buf.append(String.format("types@%d:%n", i));
+                        for (int j = 0; j < ptypes.length; j++) {
+                            ProfiledType ptype = ptypes[j];
+                            buf.append(String.format("  %.3f %s%n", ptype.probability, ptype.type));
+                        }
+                        buf.append(String.format("  %.3f <not recorded>%n", typeProfile.getNotRecordedProbability()));
+                    }
+                }
+            }
+
+            boolean firstDeoptReason = true;
+            for (RiDeoptReason reason: RiDeoptReason.values()) {
+                int count = profilingInfo.getDeoptimizationCount(reason);
+                if (count > 0) {
+                    if (firstDeoptReason) {
+                        buf.append("deoptimization history").append(NEW_LINE);
+                        firstDeoptReason = false;
+                    }
+                    buf.append(String.format("  %s: %d%n", reason.name(), count));
+                }
+            }
+        }
+        return buf.toString();
+    }
 }
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiResolvedMethod.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiResolvedMethod.java	Thu May 03 11:05:46 2012 +0200
@@ -224,9 +224,4 @@
      * @return {@code true} if this method can be inlined
      */
     boolean canBeInlined();
-
-    /**
-     * Dumps the recorded profiling information to TTY.
-     */
-    void dumpProfile();
 }
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiType.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiType.java	Thu May 03 11:05:46 2012 +0200
@@ -50,13 +50,7 @@
          * The runtime representation of the "hub" of this type--that is, the closest part of the type
          * representation which is typically stored in the object header.
          */
-        ObjectHub,
-
-        /**
-         * The runtime representation of the type information for an object, which is typically used
-         * for subtype tests.
-         */
-        TypeInfo
+        ObjectHub
     }
 
     /**
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiTypeProfile.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiTypeProfile.java	Thu May 03 11:05:46 2012 +0200
@@ -30,27 +30,52 @@
  * decisions like speculative inlining, etc.
  */
 public final class RiTypeProfile implements Serializable {
-    /**
-     *
-     */
+
     private static final long serialVersionUID = -6877016333706838441L;
 
-    private final RiResolvedType[] types;
-    private final double notRecordedProbability;
-    private final double[] probabilities;
+    /**
+     * A profiled type that has a probability. Profiled types are naturally sorted in
+     * descending order of their probabilities.
+     */
+    public static class ProfiledType implements Comparable<ProfiledType> {
+        public final RiResolvedType type;
+        public final double probability;
 
-    public RiTypeProfile(RiResolvedType[] types, double notRecordedProbability, double[] probabilites) {
-        this.types = types;
-        this.notRecordedProbability = notRecordedProbability;
-        this.probabilities = probabilites;
+        public ProfiledType(RiResolvedType type, double probability) {
+            this.type = type;
+            this.probability = probability;
+        }
+
+        @Override
+        public int compareTo(ProfiledType o) {
+            if (probability > o.probability) {
+                return -1;
+            } else if (probability < o.probability) {
+                return 1;
+            }
+            return 0;
+        }
     }
 
+    private final double notRecordedProbability;
+    private final ProfiledType[] ptypes;
+
     /**
-     * The estimated probabilities of the different receivers. This array needs to have the same length as the array returned by
-     * {@link RiTypeProfile#types}.
+     * Determines if an array of profiled types are sorted in descending order of their probabilities.
      */
-    public double[] getProbabilities() {
-        return probabilities;
+    public static boolean isSorted(ProfiledType[] ptypes) {
+        for (int i = 1; i < ptypes.length; i++) {
+            if (ptypes[i - 1].probability < ptypes[i].probability) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public RiTypeProfile(ProfiledType[] ptypes, double notRecordedProbability) {
+        this.ptypes = ptypes;
+        this.notRecordedProbability = notRecordedProbability;
+        assert isSorted(ptypes);
     }
 
     /**
@@ -62,10 +87,9 @@
     }
 
     /**
-     * A list of receivers for which the runtime has recorded probability information. This array needs to have the same
-     * length as {@link RiTypeProfile#probabilities}.
+     * A list of types for which the runtime has recorded probability information.
      */
-    public RiResolvedType[] getTypes() {
-        return types;
+    public ProfiledType[] getTypes() {
+        return ptypes;
     }
 }
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java	Thu May 03 11:05:46 2012 +0200
@@ -871,7 +871,7 @@
         return createConstant(CiConstant.forInt(v));
     }
 
-    public XirConstant l(int v) {
+    public XirConstant l(long v) {
         return createConstant(CiConstant.forLong(v));
     }
 
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java	Thu May 03 11:05:46 2012 +0200
@@ -49,14 +49,12 @@
 
     XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type);
 
-    XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact);
+    XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiResolvedType type, RiResolvedType[] hints, boolean hintsExact);
 
     XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact);
 
     XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, RiResolvedType[] hints, boolean hintsExact);
 
-    XirSnippet genArrayCopy(XirSite site, XirArgument src, XirArgument srcPos, XirArgument dest, XirArgument destPos, XirArgument length, RiType elementType, boolean inputsSame, boolean inputsDifferent);
-
     /**
      * Generates code that checks that the {@linkplain Representation#ObjectHub hub} of
      * an object is identical to a given hub constant. In pseudo code:
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/TTY.java	Fri Apr 27 13:13:06 2012 +0200
+++ b/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/TTY.java	Thu May 03 11:05:46 2012 +0200
@@ -89,12 +89,10 @@
         }
     }
 
-    public static final String MAX_TTY_LOG_FILE_PROPERTY = "max.tty.file";
-
     public static PrintStream cachedOut;
 
-    public static void initialize() {
-        cachedOut = System.out;
+    public static void initialize(PrintStream ps) {
+        cachedOut = ps;
     }
 
     private static LogStream createLog() {
@@ -102,16 +100,7 @@
             // In case initialize() was not called.
             cachedOut = System.out;
         }
-        PrintStream newOut = cachedOut;
-        String value = System.getProperty(MAX_TTY_LOG_FILE_PROPERTY);
-        if (value != null) {
-            try {
-                newOut = new PrintStream(new FileOutputStream(value));
-            } catch (FileNotFoundException e) {
-                System.err.println("Could not open log file " + value + ": " + e);
-            }
-        }
-        return new LogStream(newOut);
+        return new LogStream(cachedOut);
     }
 
     private static final ThreadLocal<LogStream> out = new ThreadLocal<LogStream>() {
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Apr 27 13:13:06 2012 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Thu May 03 11:05:46 2012 +0200
@@ -189,6 +189,7 @@
                                                                                                                          \
   /* Support for Graal */                                                                                                \
   template(HotSpotTypeResolved_klass,             com_oracle_graal_hotspot_HotSpotTypeResolved,                 Opt) \
+  template(HotSpotKlassOop_klass,                 com_oracle_graal_hotspot_HotSpotKlassOop,                     Opt) \
   template(HotSpotType_klass,                     com_oracle_graal_hotspot_HotSpotType,                         Opt) \
   template(HotSpotField_klass,                    com_oracle_graal_hotspot_HotSpotField,                        Opt) \
   template(HotSpotCompiledMethod_klass,           com_oracle_graal_hotspot_HotSpotCompiledMethod,               Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Apr 27 13:13:06 2012 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu May 03 11:05:46 2012 +0200
@@ -279,6 +279,7 @@
   template(com_oracle_graal_hotspot_HotSpotOptions,               "com/oracle/graal/hotspot/HotSpotOptions")                      \
   template(com_oracle_graal_hotspot_HotSpotTypeResolved,          "com/oracle/graal/hotspot/ri/HotSpotTypeResolvedImpl")          \
   template(com_oracle_graal_hotspot_HotSpotType,                  "com/oracle/graal/hotspot/ri/HotSpotType")                      \
+  template(com_oracle_graal_hotspot_HotSpotKlassOop,              "com/oracle/graal/hotspot/ri/HotSpotKlassOop")                  \
   template(com_oracle_graal_hotspot_HotSpotExceptionHandler,      "com/oracle/graal/hotspot/ri/HotSpotExceptionHandler")          \
   template(com_oracle_graal_hotspot_HotSpotProxy,                 "com/oracle/graal/hotspot/HotSpotProxy")                        \
   template(com_oracle_graal_hotspot_Compiler,                     "com/oracle/graal/hotspot/Compiler")                            \
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Fri Apr 27 13:13:06 2012 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Thu May 03 11:05:46 2012 +0200
@@ -743,8 +743,7 @@
     case 's':
     case 'c':
     case 'i':
-      fatal("int-sized values not expected in DataPatch")
-      ;
+      fatal("int-sized values not expected in DataPatch");
       break;
     case 'f':
     case 'j':
@@ -773,9 +772,9 @@
       address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
       Handle obj = CiConstant::object(constant);
 
-      if (obj->is_a(HotSpotTypeResolved::klass())) {
+      if (obj->is_a(HotSpotKlassOop::klass())) {
         assert(!obj.is_null(), "");
-        *((jobject*) operand) = JNIHandles::make_local(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(obj)));
+        *((jobject*) operand) = JNIHandles::make_local(java_lang_Class::as_klassOop(HotSpotKlassOop::javaMirror(obj)));
         _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
         TRACE_graal_3("relocating (HotSpotType) at %016x/%016x", instruction, operand);
       } else {
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Fri Apr 27 13:13:06 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu May 03 11:05:46 2012 +0200
@@ -1111,6 +1111,30 @@
   return JNIHandles::make_local(array);
 }
 
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_decodePC(JNIEnv *, jobject, jlong pc) {
+  TRACE_graal_3("CompilerToVM::decodePC");
+
+  VM_ENTRY_MARK;
+
+  stringStream(st);
+  CodeBlob* blob = CodeCache::find_blob_unsafe((void*) pc);
+  if (blob == NULL) {
+    st.print("[unidentified pc]");
+  } else {
+    st.print(blob->name());
+
+    nmethod* nm = blob->as_nmethod_or_null();
+    if (nm != NULL && nm->method() != NULL) {
+      st.print(" %s.", nm->method()->method_holder()->klass_part()->external_name());
+      nm->method()->name()->print_symbol_on(&st);
+      st.print("  @ %d", pc - (jlong) nm->entry_point());
+    }
+  }
+  Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL);
+  return JNIHandles::make_local(result());
+
+}
+
 
 #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))
@@ -1179,6 +1203,7 @@
   {CC"executeCompiledMethodVarargs",      CC"("HS_COMP_METHOD "["OBJECT")"OBJECT,               FN_PTR(executeCompiledMethodVarargs)},
   {CC"RiMethod_vtableEntryOffset",        CC"("RESOLVED_METHOD")I",                             FN_PTR(RiMethod_vtableEntryOffset)},
   {CC"getDeoptedLeafGraphIds",            CC"()[J",                                             FN_PTR(getDeoptedLeafGraphIds)},
+  {CC"decodePC",                          CC"(J)"STRING,                                        FN_PTR(decodePC)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalJavaAccess.hpp	Fri Apr 27 13:13:06 2012 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu May 03 11:05:46 2012 +0200
@@ -58,6 +58,9 @@
     boolean_field(HotSpotTypeResolved, isInterface)                                     \
     int_field(HotSpotTypeResolved, instanceSize)                                        \
   end_class                                                                             \
+  start_class(HotSpotKlassOop)                                                          \
+    oop_field(HotSpotKlassOop, javaMirror, "Ljava/lang/Class;")                         \
+    end_class                                                                           \
   start_class(HotSpotMethodResolved)                                                    \
     oop_field(HotSpotMethodResolved, compiler, "Lcom/oracle/graal/hotspot/Compiler;")   \
     oop_field(HotSpotMethodResolved, name, "Ljava/lang/String;")                        \
--- a/src/share/vm/runtime/frame.cpp	Fri Apr 27 13:13:06 2012 +0200
+++ b/src/share/vm/runtime/frame.cpp	Thu May 03 11:05:46 2012 +0200
@@ -740,8 +740,9 @@
     } else if (_cb->is_nmethod()) {
       methodOop m = ((nmethod *)_cb)->method();
       if (m != NULL) {
+        address code = _cb->code_begin();
         m->name_and_sig_as_C_string(buf, buflen);
-        st->print("J  %s", buf);
+        st->print("J  %s [" PTR_FORMAT "+%d]", buf, code, pc() - code);
       } else {
         st->print("J  " PTR_FORMAT, pc());
       }