changeset 15528:a3f897fb3289

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 05 May 2014 22:18:46 +0200
parents ff5cacf47b68 (current diff) fbe9e7088e35 (diff)
children c5ce68561b75
files
diffstat 25 files changed, 1188 insertions(+), 270 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Sat May 03 21:46:35 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon May 05 22:18:46 2014 +0200
@@ -203,7 +203,7 @@
             boxingSnippets.lower((BoxNode) n, tool);
         } else if (n instanceof UnboxNode) {
             boxingSnippets.lower((UnboxNode) n, tool);
-        } else if (n instanceof DeoptimizeNode || n instanceof UnwindNode) {
+        } else if (n instanceof DeoptimizeNode || n instanceof UnwindNode || n instanceof FloatRemNode) {
             /* No lowering, we generate LIR directly for these nodes. */
         } else {
             throw GraalInternalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Sat May 03 21:46:35 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Mon May 05 22:18:46 2014 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "%")
-public final class FloatRemNode extends FloatArithmeticNode implements Canonicalizable {
+public class FloatRemNode extends FloatArithmeticNode implements Canonicalizable, Lowerable {
 
     public FloatRemNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) {
         super(stamp, x, y, isStrictFP);
@@ -57,6 +57,11 @@
     }
 
     @Override
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+
+    @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
         builder.setResult(this, gen.emitRem(builder.operand(x()), builder.operand(y()), null));
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Sat May 03 21:46:35 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Mon May 05 22:18:46 2014 +0200
@@ -200,7 +200,7 @@
     private void connectBlocks() {
         for (Block block : reversePostOrder) {
             List<Block> predecessors = new ArrayList<>(4);
-            double probability = 0;
+            double probability = block.getBeginNode() instanceof StartNode ? 1D : 0D;
             for (Node predNode : block.getBeginNode().cfgPredecessors()) {
                 Block predBlock = nodeToBlock.get(predNode);
                 if (predBlock.getId() >= 0) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java	Sat May 03 21:46:35 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java	Mon May 05 22:18:46 2014 +0200
@@ -57,10 +57,11 @@
  */
 public abstract class BaseReduction extends PostOrderNodeIterator<State> {
 
-    protected static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved");
-    protected static final DebugMetric metricGuardingPiNodeRemoved = Debug.metric("GuardingPiNodeRemoved");
-    protected static final DebugMetric metricFixedGuardNodeRemoved = Debug.metric("FixedGuardNodeRemoved");
-    protected static final DebugMetric metricMethodResolved = Debug.metric("MethodResolved");
+    protected static final DebugMetric metricCheckCastRemoved = Debug.metric("FSR-CheckCastRemoved");
+    protected static final DebugMetric metricGuardingPiNodeRemoved = Debug.metric("FSR-GuardingPiNodeRemoved");
+    protected static final DebugMetric metricFixedGuardNodeRemoved = Debug.metric("FSR-FixedGuardNodeRemoved");
+    protected static final DebugMetric metricMethodResolved = Debug.metric("FSR-MethodResolved");
+    protected static final DebugMetric metricUnconditionalDeoptInserted = Debug.metric("FSR-UnconditionalDeoptInserted");
 
     /**
      * <p>
@@ -95,6 +96,7 @@
          * a bug in FlowSensitiveReduction (the code was reachable, after all).
          */
         public void doRewrite(LogicNode falseConstant) {
+            metricUnconditionalDeoptInserted.increment();
             StructuredGraph graph = fixed.graph();
             // have to insert a FixedNode other than a ControlSinkNode
             FixedGuardNode buckStopsHere = graph.add(new FixedGuardNode(falseConstant, deoptReason, DeoptimizationAction.None));
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java	Sat May 03 21:46:35 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java	Mon May 05 22:18:46 2014 +0200
@@ -122,7 +122,7 @@
         assert !StampTool.isObjectAlwaysNull(subject) : "Null as per stamp subjects should have been handled above";
 
         // --------- checkCast deemed unsatisfiable by subject-stamp alone ---------
-        if (state.knownNotToConform(subject, toType)) {
+        if (state.knownNotToPassCheckCast(subject, toType)) {
             postponedDeopts.addDeoptBefore(checkCast, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException);
             state.impossiblePath();
             // let FixedGuardNode(false).simplify() prune the dead-code control-path
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Sat May 03 21:46:35 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Mon May 05 22:18:46 2014 +0200
@@ -65,11 +65,12 @@
  */
 public final class EquationalReasoner {
 
-    private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved");
-    private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved");
-    private static final DebugMetric metricObjectEqualsRemoved = Debug.metric("ObjectEqualsRemoved");
-    private static final DebugMetric metricEquationalReasoning = Debug.metric("EquationalReasoning");
-    private static final DebugMetric metricDowncasting = Debug.metric("Downcasting");
+    private static final DebugMetric metricInstanceOfRemoved = Debug.metric("FSR-InstanceOfRemoved");
+    private static final DebugMetric metricNullCheckRemoved = Debug.metric("FSR-NullCheckRemoved");
+    private static final DebugMetric metricObjectEqualsRemoved = Debug.metric("FSR-ObjectEqualsRemoved");
+    private static final DebugMetric metricEquationalReasoning = Debug.metric("FSR-EquationalReasoning");
+    private static final DebugMetric metricDowncasting = Debug.metric("FSR-Downcasting");
+    private static final DebugMetric metricNullInserted = Debug.metric("FSR-NullInserted");
 
     private final StructuredGraph graph;
     private final CanonicalizerTool tool;
@@ -114,6 +115,7 @@
      */
     public void forceState(State s) {
         state = s;
+        assert state.repOK();
         substs.clear();
         added.clear();
         visited = null;
@@ -235,6 +237,17 @@
             // picked cached substitution
             return result;
         }
+        if (FlowUtil.hasLegalObjectStamp(v) && state.isNull(v)) {
+            // it's ok to return nullConstant in deverbosify unlike in downcast
+            metricNullInserted.increment();
+            return nullConstant;
+        }
+        if (v instanceof ValueProxy) {
+            return v;
+        }
+        if (!(n instanceof FloatingNode)) {
+            return n;
+        }
         if ((visited != null && visited.contains(n)) || added.contains(v)) {
             return v;
         }
@@ -252,25 +265,13 @@
          * Past this point, if we ever want `n` to be deverbosified, it must be looked-up by one of
          * the cases above. One sure way to achieve that is with `rememberSubstitution(old, new)`
          */
-        if (v instanceof ValueProxy) {
-            return downcast(v);
-        }
 
-        if (n instanceof FloatingNode) {
-            /*
-             * `deverbosifyFloatingNode()` will drill down over floating inputs, when that not
-             * possible anymore it resorts to calling `downcast()`. Thus it's ok to take the
-             * `deverbosifyFloatingNode()` route first, as no downcasting opportunity will be
-             * missed.
-             */
-            return deverbosifyFloatingNode((FloatingNode) n);
-        }
-
-        if (FlowUtil.hasLegalObjectStamp(v)) {
-            return downcast(v);
-        }
-
-        return n;
+        /*
+         * `deverbosifyFloatingNode()` will drill down over floating inputs, when that not possible
+         * anymore it resorts to calling `downcast()`. Thus it's ok to take the
+         * `deverbosifyFloatingNode()` route first, as no downcasting opportunity will be missed.
+         */
+        return deverbosifyFloatingNode((FloatingNode) n);
     }
 
     /**
@@ -334,16 +335,7 @@
         }
         if (changed == null) {
             assert visited.contains(f) || added.contains(f);
-            if (FlowUtil.hasLegalObjectStamp(f)) {
-                /*
-                 * No input has changed doesn't imply there's no witness to refine the
-                 * floating-object value.
-                 */
-                ValueNode d = downcast(f);
-                return d;
-            } else {
-                return f;
-            }
+            return f;
         }
         FlowUtil.inferStampAndCheck(changed);
         added.add(changed);
@@ -441,6 +433,8 @@
                 return baseCaseIsNullNode((IsNullNode) condition);
             } else if (condition instanceof ObjectEqualsNode) {
                 return baseCaseObjectEqualsNode((ObjectEqualsNode) condition);
+            } else if (condition instanceof ShortCircuitOrNode) {
+                return baseCaseShortCircuitOrNode((ShortCircuitOrNode) condition);
             }
         }
         return condition;
@@ -465,6 +459,11 @@
         if (state.isNull(scrutinee)) {
             metricInstanceOfRemoved.increment();
             return falseConstant;
+        } else if (state.knownNotToPassInstanceOf(scrutinee, instanceOf.type())) {
+            // scrutinee turns out to be null -> falseConstant right answer
+            // scrutinee not null, but known-not-to-conform -> falseConstant
+            metricInstanceOfRemoved.increment();
+            return falseConstant;
         } else if (state.isNonNull(scrutinee) && state.knownToConform(scrutinee, instanceOf.type())) {
             metricInstanceOfRemoved.increment();
             return trueConstant;
@@ -477,21 +476,19 @@
      *         performed; otherwise the unmodified argument.
      *
      */
-    private FloatingNode baseCaseIsNullNode(IsNullNode isNull) {
-        ValueNode object = isNull.object();
+    private FloatingNode baseCaseIsNullNode(IsNullNode isNu) {
+        ValueNode object = isNu.object();
         if (!FlowUtil.hasLegalObjectStamp(object)) {
-            return isNull;
+            return isNu;
         }
-        ValueNode scrutinee = GraphUtil.unproxify(isNull.object());
-        GuardingNode evidence = nonTrivialNullAnchor(scrutinee);
-        if (evidence != null) {
+        if (state.isNull(object)) {
             metricNullCheckRemoved.increment();
             return trueConstant;
-        } else if (state.isNonNull(scrutinee)) {
+        } else if (state.isNonNull(object)) {
             metricNullCheckRemoved.increment();
             return falseConstant;
         }
-        return isNull;
+        return isNu;
     }
 
     /**
@@ -515,6 +512,38 @@
     }
 
     /**
+     * The following is tried:
+     *
+     * <ol>
+     * <li>
+     * A {@link com.oracle.graal.phases.common.cfs.Witness} that is at check-cast level level
+     * doesn't entail {@link com.oracle.graal.nodes.calc.IsNullNode} (on its own) nor
+     * {@link com.oracle.graal.nodes.java.InstanceOfNode} (also on its own) but of course it entails
+     * <code>(IsNull || IsInstanceOf)</code>. Good thing
+     * {@link com.oracle.graal.phases.common.cfs.CastCheckExtractor} detects that very pattern.</li>
+     * <li>
+     * Otherwise return the unmodified argument (later on,
+     * {@link #deverbosifyFloatingNode(com.oracle.graal.nodes.calc.FloatingNode)} will attempt to
+     * simplify the {@link com.oracle.graal.nodes.ShortCircuitOrNode}).</li>
+     * </ol>
+     *
+     * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was made;
+     *         otherwise the unmodified argument.
+     */
+    private LogicNode baseCaseShortCircuitOrNode(ShortCircuitOrNode orNode) {
+        CastCheckExtractor cast = CastCheckExtractor.extract(orNode);
+        if (cast != null) {
+            if (state.knownToConform(cast.subject, cast.type)) {
+                return trueConstant;
+            } else if (state.knownNotToPassCheckCast(cast.subject, cast.type)) {
+                return falseConstant;
+            }
+            return orNode;
+        }
+        return orNode;
+    }
+
+    /**
      * It's always ok to use "<code>downcast(object)</code>" instead of " <code>object</code>"
      * because this method re-wraps the argument in a {@link com.oracle.graal.nodes.PiNode} only if
      * the new stamp is strictly more refined than the original.
@@ -558,6 +587,7 @@
 
         PiNode untrivialNull = nonTrivialNull(scrutinee);
         if (untrivialNull != null) {
+            metricNullInserted.increment();
             return untrivialNull;
         }
 
@@ -646,24 +676,6 @@
     }
 
     /**
-     * <p>
-     * If the argument is known null due to its stamp, there's no need to have an anchor for that
-     * fact and this method returns null.
-     * </p>
-     *
-     * <p>
-     * Otherwise, if an anchor is found it is returned, null otherwise.
-     * </p>
-     */
-    public GuardingNode nonTrivialNullAnchor(ValueNode object) {
-        assert FlowUtil.hasLegalObjectStamp(object);
-        if (StampTool.isObjectAlwaysNull(object)) {
-            return null;
-        }
-        return state.knownNull.get(GraphUtil.unproxify(object));
-    }
-
-    /**
      *
      * This method returns:
      * <ul>
@@ -680,7 +692,7 @@
      */
     public PiNode nonTrivialNull(ValueNode object) {
         assert FlowUtil.hasLegalObjectStamp(object);
-        GuardingNode anchor = nonTrivialNullAnchor(object);
+        GuardingNode anchor = state.nonTrivialNullAnchor(object);
         if (anchor == null) {
             return null;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Evidence.java	Mon May 05 22:18:46 2014 +0200
@@ -0,0 +1,61 @@
+/*
+ * 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.phases.common.cfs;
+
+import com.oracle.graal.nodes.extended.GuardingNode;
+
+public class Evidence {
+
+    public final GuardingNode success;
+    public final boolean failure;
+
+    public Evidence(GuardingNode success, boolean failure) {
+        this.success = success;
+        this.failure = failure;
+        assert repOK();
+    }
+
+    public Evidence(GuardingNode success) {
+        this(success, false);
+    }
+
+    private Evidence(boolean failure) {
+        this(null, failure);
+    }
+
+    public boolean isPositive() {
+        return success != null;
+    }
+
+    public boolean isNegative() {
+        return failure;
+    }
+
+    private boolean repOK() {
+        // either success or failure, ie boolean-XOR
+        return (success != null) != failure;
+    }
+
+    public static Evidence COUNTEREXAMPLE = new Evidence(true);
+
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FixedGuardReduction.java	Sat May 03 21:46:35 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FixedGuardReduction.java	Mon May 05 22:18:46 2014 +0200
@@ -23,9 +23,7 @@
 package com.oracle.graal.phases.common.cfs;
 
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.IsNullNode;
 import com.oracle.graal.nodes.extended.GuardingNode;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.tiers.PhaseContext;
 
 /**
@@ -99,118 +97,33 @@
             return;
         }
 
-        /*
-         * Attempt to eliminate the current FixedGuardNode by using another GuardingNode already in
-         * scope and with equivalent condition.
-         */
+        final boolean isTrue = !f.isNegated();
+        final Evidence evidence = state.outcome(isTrue, f.condition());
 
-        GuardingNode existingGuard = f.isNegated() ? state.falseFacts.get(f.condition()) : state.trueFacts.get(f.condition());
-        if (existingGuard != null) {
-            // assert existingGuard instanceof FixedGuardNode;
-            metricFixedGuardNodeRemoved.increment();
-            f.replaceAtUsages(existingGuard.asNode());
-            graph.removeFixed(f);
+        // can't produce evidence, must be information gain
+        if (evidence == null) {
+            state.addFact(isTrue, f.condition(), f);
             return;
         }
 
-        final LogicNode cond = f.condition();
-        final boolean isTrue = !f.isNegated();
-
-        /*
-         * A FixedGuardNode can only be removed provided a replacement anchor is found (so called
-         * "evidence"), ie an anchor that amounts to the same combination of (negated, condition) as
-         * for the FixedGuardNode at hand. Just deverbosifying the condition in place isn't
-         * semantics-preserving.
-         */
-
-        // TODO what about isDependencyTainted
-
-        if (cond instanceof IsNullNode) {
-            final IsNullNode isNullNode = (IsNullNode) cond;
-            if (isTrue) {
-                // grab an anchor attesting nullness
-                final GuardingNode replacement = reasoner.nonTrivialNullAnchor(isNullNode.object());
-                if (replacement != null) {
-                    removeFixedGuardNode(f, replacement);
-                    return;
-                }
-                if (state.isNonNull(isNullNode.object())) {
-                    markFixedGuardNodeAlwaysFails(f);
-                    return;
-                }
-                // can't produce evidence, fall-through to addFact
-            } else {
-                // grab an anchor attesting non-nullness
-                final Witness w = state.typeInfo(isNullNode.object());
-                if (w != null && w.isNonNull()) {
-                    removeFixedGuardNode(f, w.guard());
-                    return;
-                }
-                if (state.isNull(isNullNode.object())) {
-                    markFixedGuardNodeAlwaysFails(f);
-                    return;
-                }
-                // can't produce evidence, fall-through to addFact
-            }
-        } else if (cond instanceof InstanceOfNode) {
-            final InstanceOfNode iOf = (InstanceOfNode) cond;
-            final Witness w = state.typeInfo(iOf.object());
-            if (isTrue) {
-                // grab an anchor attesting instanceof
-                if (w != null) {
-                    if (w.isNonNull() && w.type() != null) {
-                        if (iOf.type().isAssignableFrom(w.type())) {
-                            removeFixedGuardNode(f, w.guard());
-                            return;
-                        }
-                        if (State.knownNotToConform(w.type(), iOf.type())) {
-                            markFixedGuardNodeAlwaysFails(f);
-                            return;
-                        }
-                    }
-                }
-                if (state.isNull(iOf.object())) {
-                    markFixedGuardNodeAlwaysFails(f);
-                    return;
-                }
-                // can't produce evidence, fall-through to addFact
-            } else {
-                // grab an anchor attesting not-instanceof
-                // (1 of 2) attempt determining nullness
-                final GuardingNode nullGuard = reasoner.nonTrivialNullAnchor(iOf.object());
-                if (nullGuard != null) {
-                    removeFixedGuardNode(f, nullGuard);
-                    return;
-                }
-                // (2 of 2) attempt determining known-not-to-conform
-                if (w != null && !w.cluelessAboutType()) {
-                    if (State.knownNotToConform(w.type(), iOf.type())) {
-                        removeFixedGuardNode(f, w.guard());
-                        return;
-                    }
-                }
-                // can't produce evidence, fall-through to addFact
-            }
-        } else if (isTrue && cond instanceof ShortCircuitOrNode) {
-            CastCheckExtractor cce = CastCheckExtractor.extract(cond);
-            if (cce != null && !State.isDependencyTainted(cce.subject, f)) {
-                // grab an anchor attesting check-cast
-                Witness w = state.typeInfo(cce.subject);
-                if (w != null && w.type() != null) {
-                    if (cce.type.isAssignableFrom(w.type())) {
-                        removeFixedGuardNode(f, w.guard());
-                        return;
-                    }
-                    if (State.knownNotToConform(w.type(), cce.type)) {
-                        markFixedGuardNodeAlwaysFails(f);
-                        return;
-                    }
-                }
-            }
-            // can't produce evidence, fall-through to addFact
+        if (evidence.isPositive()) {
+            /*
+             * A FixedGuardNode can only be removed provided a replacement anchor is found (so
+             * called "evidence"), ie an anchor that amounts to the same combination of (negated,
+             * condition) as for the FixedGuardNode at hand. Just deverbosifying the condition in
+             * place isn't semantics-preserving.
+             * 
+             * Eliminate the current FixedGuardNode by using another GuardingNode already in scope,
+             * a GuardingNode that guards a condition that is at least as strong as that of the
+             * FixedGuardNode.
+             */
+            removeFixedGuardNode(f, evidence.success);
+            return;
         }
 
-        state.addFact(isTrue, cond, f);
+        assert evidence.isNegative();
+        markFixedGuardNodeAlwaysFails(f);
+
     }
 
     /**
@@ -232,9 +145,7 @@
      * </p>
      */
     private void removeFixedGuardNode(FixedGuardNode old, GuardingNode replacement) {
-        if (replacement == null) {
-            return;
-        }
+        assert replacement != null;
         metricFixedGuardNodeRemoved.increment();
         old.replaceAtUsages(replacement.asNode());
         graph.removeFixed(old);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Sat May 03 21:46:35 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Mon May 05 22:18:46 2014 +0200
@@ -54,6 +54,14 @@
  * <ul>
  * <li>simplification of side-effects free expressions, via
  * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)}
+ * <ul>
+ * <li>
+ * at certain {@link com.oracle.graal.nodes.FixedNode}, see
+ * {@link #deverbosifyInputsInPlace(com.oracle.graal.nodes.ValueNode)}</li>
+ * <li>
+ * including for devirtualization, see
+ * {@link #deverbosifyInputsCopyOnWrite(com.oracle.graal.nodes.java.MethodCallTargetNode)}</li>
+ * </ul>
  * </li>
  * <li>simplification of control-flow:
  * <ul>
@@ -76,6 +84,13 @@
  * </ol>
  * </p>
  *
+ * <p>
+ * Metrics for this phase are displayed starting with <code>FSR-</code>prefix, their counters are
+ * hosted in {@link com.oracle.graal.phases.common.cfs.BaseReduction},
+ * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner} and
+ * {@link com.oracle.graal.phases.common.cfs.State}.
+ * </p>
+ *
  * @see com.oracle.graal.phases.common.cfs.CheckCastReduction
  * @see com.oracle.graal.phases.common.cfs.GuardingPiReduction
  * @see com.oracle.graal.phases.common.cfs.FixedGuardReduction
@@ -217,13 +232,8 @@
                 // `begin` denotes the default case of the TypeSwitchNode
                 return;
             }
-            if (state.knownNotToConform(loadHub.object(), type)) {
-                postponedDeopts.addDeoptAfter(begin, UnreachedCode);
-                state.impossiblePath();
-                return;
-            }
             // it's unwarranted to assume loadHub.object() to be non-null
-            // it also seems unwarranted state.trackCC(loadHub.object(), type, begin);
+            state.trackCC(loadHub.object(), type, begin);
         }
     }
 
@@ -295,9 +305,16 @@
      *
      */
     private MethodCallTargetNode deverbosifyInputsCopyOnWrite(MethodCallTargetNode parent) {
+        final MethodCallTargetNode.InvokeKind ik = parent.invokeKind();
+        final boolean shouldTryDevirt = (ik == MethodCallTargetNode.InvokeKind.Interface || ik == MethodCallTargetNode.InvokeKind.Virtual);
+        boolean shouldDowncastReceiver = shouldTryDevirt;
         MethodCallTargetNode changed = null;
         for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) {
-            Node j = reasoner.deverbosify(i);
+            ValueNode j = (ValueNode) reasoner.deverbosify(i);
+            if (shouldDowncastReceiver) {
+                shouldDowncastReceiver = false;
+                j = reasoner.downcast(j);
+            }
             if (i != j) {
                 assert j != parent;
                 if (changed == null) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java	Sat May 03 21:46:35 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java	Mon May 05 22:18:46 2014 +0200
@@ -50,10 +50,10 @@
  */
 public final class State extends MergeableState<State> implements Cloneable {
 
-    private static final DebugMetric metricTypeRegistered = Debug.metric("TypeRegistered");
-    private static final DebugMetric metricNullnessRegistered = Debug.metric("NullnessRegistered");
-    private static final DebugMetric metricObjectEqualsRegistered = Debug.metric("ObjectEqualsRegistered");
-    private static final DebugMetric metricImpossiblePathDetected = Debug.metric("ImpossiblePathDetected");
+    private static final DebugMetric metricTypeRegistered = Debug.metric("FSR-TypeRegistered");
+    private static final DebugMetric metricNullnessRegistered = Debug.metric("FSR-NullnessRegistered");
+    private static final DebugMetric metricObjectEqualsRegistered = Debug.metric("FSR-ObjectEqualsRegistered");
+    private static final DebugMetric metricImpossiblePathDetected = Debug.metric("FSR-ImpossiblePathDetected");
 
     /**
      * <p>
@@ -141,6 +141,18 @@
         this.falseFacts = new IdentityHashMap<>(other.falseFacts);
     }
 
+    public boolean repOK() {
+        // trueFacts and falseFacts disjoint
+        for (LogicNode trueFact : trueFacts.keySet()) {
+            assert !falseFacts.containsKey(trueFact) : trueFact + " tracked as both true and false fact.";
+        }
+        // no scrutinee tracked as both known-null and known-non-null
+        for (ValueNode subject : knownNull.keySet()) {
+            assert !isNonNull(subject) : subject + " tracked as both known-null and known-non-null.";
+        }
+        return true;
+    }
+
     /**
      * @return A new list containing only those states that are reachable.
      */
@@ -300,6 +312,9 @@
 
         this.trueFacts = mergeTrueFacts(withReachableStates, merge);
         this.falseFacts = mergeFalseFacts(withReachableStates, merge);
+
+        assert repOK();
+
         return true;
     }
 
@@ -393,7 +408,8 @@
     }
 
     /**
-     * @return true iff the argument is known to stand for an object conforming to the given type.
+     * @return true iff the argument definitely stands for an object-value that conforms to the
+     *         given type.
      */
     public boolean knownToConform(ValueNode object, ResolvedJavaType to) {
         assert FlowUtil.hasLegalObjectStamp(object);
@@ -415,14 +431,20 @@
     }
 
     /**
-     * @return true iff the argument is known to stand for an object that definitely does not
-     *         conform to the given type.
+     * @return true iff the argument is known to stand for an object that is definitely non-null and
+     *         moreover does not conform to the given type.
      */
-    public boolean knownNotToConform(ValueNode object, ResolvedJavaType to) {
+    public boolean knownNotToPassCheckCast(ValueNode object, ResolvedJavaType to) {
         assert FlowUtil.hasLegalObjectStamp(object);
         assert !to.isPrimitive();
         final ValueNode scrutinee = GraphUtil.unproxify(object);
         if (isNull(scrutinee)) {
+            // known-null means it conforms to whatever `to`
+            // and thus passes the check-cast
+            return false;
+        }
+        if (!isNonNull(scrutinee)) {
+            // unless `null` can be ruled out, a positive answer isn't safe
             return false;
         }
         ResolvedJavaType stampType = StampTool.typeOrNull(object);
@@ -437,6 +459,34 @@
         return false;
     }
 
+    /**
+     * @return true iff the argument is known to stand for an object that definitely does not
+     *         conform to the given type (no matter whether the object turns out to be null or
+     *         non-null).
+     */
+    public boolean knownNotToPassInstanceOf(ValueNode object, ResolvedJavaType to) {
+        assert FlowUtil.hasLegalObjectStamp(object);
+        assert !to.isPrimitive();
+        final ValueNode scrutinee = GraphUtil.unproxify(object);
+        if (isNull(scrutinee)) {
+            return true;
+        }
+        ResolvedJavaType stampType = StampTool.typeOrNull(object);
+        if (stampType != null && knownNotToConform(stampType, to)) {
+            // object turns out to be null, positive answer is correct
+            // object turns out non-null, positive answer is also correct
+            return true;
+        }
+        Witness w = typeInfo(scrutinee);
+        boolean witnessAnswer = w != null && !w.cluelessAboutType() && knownNotToConform(w.type(), to);
+        if (witnessAnswer) {
+            // object turns out to be null, positive answer is correct
+            // object turns out non-null, positive answer is also correct
+            return true;
+        }
+        return false;
+    }
+
     // @formatter:off
     /**
      *   \   |     |     |     |
@@ -526,6 +576,7 @@
         Witness w = getOrElseAddTypeInfo(object);
         if (w.trackNN(anchor)) {
             versionNr++;
+            assert repOK();
             return true;
         }
         return false;
@@ -558,6 +609,7 @@
         if (w.trackCC(observed, anchor)) {
             versionNr++;
             metricTypeRegistered.increment();
+            assert repOK();
             return true;
         }
         return false;
@@ -584,6 +636,7 @@
         if (w.trackIO(observed, anchor)) {
             versionNr++;
             metricTypeRegistered.increment();
+            assert repOK();
             return true;
         }
         return false;
@@ -665,6 +718,7 @@
         } else {
             addFactPrimordial(condition, isTrue ? trueFacts : falseFacts, anchor);
         }
+        assert repOK();
     }
 
     /**
@@ -675,7 +729,7 @@
     private void addFactInstanceOf(boolean isTrue, InstanceOfNode instanceOf, GuardingNode anchor) {
         ValueNode object = instanceOf.object();
         if (isTrue) {
-            if (knownNotToConform(object, instanceOf.type())) {
+            if (knownNotToPassInstanceOf(object, instanceOf.type())) {
                 impossiblePath();
                 return;
             }
@@ -776,6 +830,7 @@
                 trackNN(original, anchor);
             }
         }
+        assert repOK();
     }
 
     /**
@@ -813,4 +868,178 @@
         falseFacts.clear();
     }
 
+    /**
+     * <p>
+     * If the argument is known null due to its stamp, there's no need to have an anchor for that
+     * fact and this method returns null.
+     * </p>
+     *
+     * <p>
+     * Otherwise, if an anchor is found it is returned, null otherwise.
+     * </p>
+     */
+    public GuardingNode nonTrivialNullAnchor(ValueNode object) {
+        assert FlowUtil.hasLegalObjectStamp(object);
+        if (StampTool.isObjectAlwaysNull(object)) {
+            return null;
+        }
+        return knownNull.get(GraphUtil.unproxify(object));
+    }
+
+    /**
+     * This method:
+     * <ul>
+     * <li>
+     * attempts to find an existing {@link com.oracle.graal.nodes.extended.GuardingNode} that
+     * implies the property stated by the arguments. If found, returns it as positive evidence.</li>
+     * <li>
+     * otherwise, if the property of interest is known not to hold, negative evidence is returned.</li>
+     * <li>
+     * otherwise, null is returned.</li>
+     * </ul>
+     */
+    public Evidence outcome(boolean isTrue, LogicNode cond) {
+
+        // attempt to find an anchor for the condition of interest, verbatim
+        if (isTrue) {
+            GuardingNode existingGuard = trueFacts.get(cond);
+            if (existingGuard != null) {
+                return new Evidence(existingGuard);
+            }
+            if (falseFacts.containsKey(cond)) {
+                return Evidence.COUNTEREXAMPLE;
+            }
+        } else {
+            GuardingNode existingGuard = falseFacts.get(cond);
+            if (existingGuard != null) {
+                return new Evidence(existingGuard);
+            }
+            if (trueFacts.containsKey(cond)) {
+                return Evidence.COUNTEREXAMPLE;
+            }
+        }
+
+        if (cond instanceof IsNullNode) {
+            return outcomeIsNullNode(isTrue, (IsNullNode) cond);
+        }
+
+        if (cond instanceof InstanceOfNode) {
+            return outcomeInstanceOfNode(isTrue, (InstanceOfNode) cond);
+        }
+
+        if (cond instanceof ShortCircuitOrNode) {
+            return outcomeShortCircuitOrNode(isTrue, (ShortCircuitOrNode) cond);
+        }
+
+        // can't produce evidence
+        return null;
+    }
+
+    /**
+     * Utility method for {@link #outcome(boolean, com.oracle.graal.nodes.LogicNode)}
+     */
+    private Evidence outcomeIsNullNode(boolean isTrue, IsNullNode isNullNode) {
+        if (isTrue) {
+            // grab an anchor attesting nullness
+            final GuardingNode replacement = nonTrivialNullAnchor(isNullNode.object());
+            if (replacement != null) {
+                return new Evidence(replacement);
+            }
+            if (isNonNull(isNullNode.object())) {
+                return Evidence.COUNTEREXAMPLE;
+            }
+        } else {
+            // grab an anchor attesting non-nullness
+            final Witness w = typeInfo(isNullNode.object());
+            if (w != null && w.isNonNull()) {
+                return new Evidence(w.guard());
+            }
+            if (isNull(isNullNode.object())) {
+                return Evidence.COUNTEREXAMPLE;
+            }
+        }
+        // can't produce evidence
+        return null;
+    }
+
+    /**
+     * Utility method for {@link #outcome(boolean, com.oracle.graal.nodes.LogicNode)}
+     */
+    private Evidence outcomeInstanceOfNode(boolean isTrue, InstanceOfNode iOf) {
+        final Witness w = typeInfo(iOf.object());
+        if (isTrue) {
+            if (isNull(iOf.object())) {
+                return Evidence.COUNTEREXAMPLE;
+            }
+            // grab an anchor attesting instanceof
+            if ((w != null) && (w.type() != null)) {
+                if (w.isNonNull()) {
+                    if (iOf.type().isAssignableFrom(w.type())) {
+                        return new Evidence(w.guard());
+                    }
+                }
+                if (State.knownNotToConform(w.type(), iOf.type())) {
+                    // null -> fails instanceof
+                    // non-null but non-conformant -> also fails instanceof
+                    return Evidence.COUNTEREXAMPLE;
+                }
+            }
+        } else {
+            // grab an anchor attesting not-instanceof
+            // (1 of 2) attempt determining nullness
+            final GuardingNode nullGuard = nonTrivialNullAnchor(iOf.object());
+            if (nullGuard != null) {
+                return new Evidence(nullGuard);
+            }
+            // (2 of 2) attempt determining known-not-to-conform
+            if (w != null && !w.cluelessAboutType()) {
+                if (State.knownNotToConform(w.type(), iOf.type())) {
+                    return new Evidence(w.guard());
+                }
+            }
+        }
+        // can't produce evidence
+        return null;
+    }
+
+    /**
+     * Utility method for {@link #outcome(boolean, com.oracle.graal.nodes.LogicNode)}
+     */
+    private Evidence outcomeShortCircuitOrNode(boolean isTrue, ShortCircuitOrNode orNode) {
+        if (!isTrue) {
+            // too tricky to reason about
+            return null;
+        }
+        CastCheckExtractor cce = CastCheckExtractor.extract(orNode);
+        if (cce != null) {
+            // grab an anchor attesting check-cast
+            Witness w = typeInfo(cce.subject);
+            if (w != null && w.type() != null) {
+                if (cce.type.isAssignableFrom(w.type())) {
+                    return new Evidence(w.guard());
+                }
+                if (isNonNull(cce.subject) && State.knownNotToConform(w.type(), cce.type)) {
+                    return Evidence.COUNTEREXAMPLE;
+                }
+            }
+        }
+        // search for positive-evidence for the first or-input
+        Evidence evidenceX = outcome(!orNode.isXNegated(), orNode.getX());
+        if (evidenceX != null && evidenceX.isPositive()) {
+            return evidenceX;
+        }
+        // search for positive-evidence for the second or-input
+        Evidence evidenceY = outcome(!orNode.isYNegated(), orNode.getY());
+        if (evidenceY != null && evidenceY.isPositive()) {
+            return evidenceY;
+        }
+        // check for contradictions on both or-inputs
+        if (evidenceX != null && evidenceY != null) {
+            assert evidenceX.isNegative() && evidenceY.isNegative();
+            return Evidence.COUNTEREXAMPLE;
+        }
+        // can't produce evidence
+        return null;
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalJUnitCore.java	Mon May 05 22:18:46 2014 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014, 2014, 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.test;
+
+import java.util.*;
+
+import junit.runner.*;
+
+import org.junit.internal.*;
+import org.junit.runner.*;
+import org.junit.runner.notification.*;
+
+public class GraalJUnitCore {
+
+    /**
+     * Run the tests contained in the classes named in the <code>args</code>. If all tests run
+     * successfully, exit with a status of 0. Otherwise exit with a status of 1. Write feedback
+     * while tests are running and write stack traces for all failed tests after the tests all
+     * complete.
+     *
+     * @param args names of classes in which to find tests to run
+     */
+    public static void main(String... args) {
+        JUnitSystem system = new RealSystem();
+        JUnitCore junitCore = new JUnitCore();
+        system.out().println("GraalJUnitCore");
+        system.out().println("JUnit version " + Version.id());
+        List<Class<?>> classes = new ArrayList<>();
+        List<Failure> missingClasses = new ArrayList<>();
+        boolean verbose = false;
+        boolean enableTiming = false;
+        for (String each : args) {
+            if (each.charAt(0) == '-') {
+                // command line arguments
+                if (each.contentEquals("-JUnitVerbose")) {
+                    verbose = true;
+                } else if (each.contentEquals("-JUnitEnableTiming")) {
+                    enableTiming = true;
+                } else {
+                    system.out().println("Unknown command line argument: " + each);
+                }
+
+            } else {
+                try {
+                    classes.add(Class.forName(each));
+                } catch (ClassNotFoundException e) {
+                    system.out().println("Could not find class: " + each);
+                    Description description = Description.createSuiteDescription(each);
+                    Failure failure = new Failure(description, e);
+                    missingClasses.add(failure);
+                }
+            }
+        }
+        GraalJUnitRunListener graalListener;
+        if (!verbose) {
+            graalListener = new GraalTextListener(system);
+        } else {
+            graalListener = new GraalVerboseTextListener(system);
+        }
+        if (enableTiming) {
+            graalListener = new TimingDecorator(graalListener);
+        }
+        junitCore.addListener(GraalTextListener.createRunListener(graalListener));
+        Result result = junitCore.run(classes.toArray(new Class[0]));
+        for (Failure each : missingClasses) {
+            result.getFailures().add(each);
+        }
+        System.exit(result.wasSuccessful() ? 0 : 1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalJUnitRunListener.java	Mon May 05 22:18:46 2014 +0200
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014, 2014, 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.test;
+
+import java.io.*;
+
+import org.junit.internal.*;
+import org.junit.runner.*;
+import org.junit.runner.notification.*;
+
+public interface GraalJUnitRunListener {
+
+    /**
+     * Called before any tests have been run.
+     *
+     * @param description describes the tests to be run
+     */
+    public void testRunStarted(Description description);
+
+    /**
+     * Called when all tests have finished
+     *
+     * @param result the summary of the test run, including all the tests that failed
+     */
+    public void testRunFinished(Result result);
+
+    /**
+     * Called when a test class is about to be started.
+     *
+     * @param clazz the test class
+     */
+    void testClassStarted(Class<?> clazz);
+
+    /**
+     * Called when all tests of a test class have finished.
+     *
+     * @param clazz the test class
+     */
+    void testClassFinished(Class<?> clazz);
+
+    /**
+     * Called when an atomic test is about to be started. This is also called for ignored tests.
+     *
+     * @param description the description of the test that is about to be run (generally a class and
+     *            method name)
+     */
+    void testStarted(Description description);
+
+    /**
+     * Called when an atomic test has finished, whether the test succeeds, fails or is ignored.
+     *
+     * @param description the description of the test that just ran
+     */
+    void testFinished(Description description);
+
+    /**
+     * Called when an atomic test fails.
+     *
+     * @param failure describes the test that failed and the exception that was thrown
+     */
+    void testFailed(Failure failure);
+
+    /**
+     * Called when a test will not be run, generally because a test method is annotated with
+     * {@link org.junit.Ignore}.
+     *
+     * @param description describes the test that will not be run
+     */
+    public void testIgnored(Description description);
+
+    /**
+     * Called when an atomic test succeeds.
+     *
+     * @param description describes the test that will not be run
+     */
+    void testSucceeded(Description description);
+
+    /**
+     * Called when an atomic test flags that it assumes a condition that is false
+     *
+     * @param failure describes the test that failed and the {@link AssumptionViolatedException}
+     *            that was thrown
+     */
+    public void testAssumptionFailure(Failure failure);
+
+    /**
+     * Called after {@link #testClassFinished(Class)}.
+     */
+    public void testClassFinishedDelimiter();
+
+    /**
+     * Called after {@link #testClassStarted(Class)}
+     */
+    public void testClassStartedDelimiter();
+
+    /**
+     * Called after {@link #testStarted(Description)}
+     */
+    public void testStartedDelimiter();
+
+    /**
+     * Called after {@link #testFailed(Failure)}
+     */
+    public void testFinishedDelimiter();
+
+    public PrintStream getWriter();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalJUnitRunListenerDecorator.java	Mon May 05 22:18:46 2014 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2014, 2014, 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.test;
+
+import java.io.*;
+
+import org.junit.runner.*;
+import org.junit.runner.notification.*;
+
+public class GraalJUnitRunListenerDecorator implements GraalJUnitRunListener {
+
+    private final GraalJUnitRunListener l;
+
+    public GraalJUnitRunListenerDecorator(GraalJUnitRunListener l) {
+        this.l = l;
+    }
+
+    @Override
+    public void testRunStarted(Description description) {
+        l.testRunStarted(description);
+    }
+
+    @Override
+    public void testRunFinished(Result result) {
+        l.testRunFinished(result);
+    }
+
+    @Override
+    public void testAssumptionFailure(Failure failure) {
+        l.testAssumptionFailure(failure);
+    }
+
+    @Override
+    public void testIgnored(Description description) {
+        l.testIgnored(description);
+    }
+
+    @Override
+    public void testClassStarted(Class<?> clazz) {
+        l.testClassStarted(clazz);
+    }
+
+    @Override
+    public void testClassFinished(Class<?> clazz) {
+        l.testClassFinished(clazz);
+    }
+
+    @Override
+    public void testStarted(Description description) {
+        l.testStarted(description);
+    }
+
+    @Override
+    public void testFinished(Description description) {
+        l.testFinished(description);
+    }
+
+    @Override
+    public void testFailed(Failure failure) {
+        l.testFailed(failure);
+    }
+
+    @Override
+    public void testSucceeded(Description description) {
+        l.testSucceeded(description);
+    }
+
+    @Override
+    public PrintStream getWriter() {
+        return l.getWriter();
+    }
+
+    public void testClassFinishedDelimiter() {
+        l.testClassFinishedDelimiter();
+    }
+
+    public void testClassStartedDelimiter() {
+        l.testClassStartedDelimiter();
+    }
+
+    public void testStartedDelimiter() {
+        l.testStartedDelimiter();
+    }
+
+    public void testFinishedDelimiter() {
+        l.testFinishedDelimiter();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTextListener.java	Mon May 05 22:18:46 2014 +0200
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2014, 2014, 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.test;
+
+import java.io.*;
+
+import org.junit.internal.*;
+import org.junit.runner.*;
+import org.junit.runner.notification.*;
+
+public class GraalTextListener implements GraalJUnitRunListener {
+
+    private final PrintStream fWriter;
+
+    public GraalTextListener(JUnitSystem system) {
+        this(system.out());
+    }
+
+    public GraalTextListener(PrintStream writer) {
+        fWriter = writer;
+    }
+
+    @Override
+    public PrintStream getWriter() {
+        return fWriter;
+    }
+
+    @Override
+    public void testRunStarted(Description description) {
+    }
+
+    @Override
+    public void testRunFinished(Result result) {
+    }
+
+    @Override
+    public void testAssumptionFailure(Failure failure) {
+    }
+
+    @Override
+    public void testClassStarted(Class<?> clazz) {
+    }
+
+    @Override
+    public void testClassFinished(Class<?> clazz) {
+    }
+
+    @Override
+    public void testStarted(Description description) {
+        getWriter().print('.');
+    }
+
+    @Override
+    public void testFinished(Description description) {
+    }
+
+    @Override
+    public void testFailed(Failure failure) {
+        getWriter().print('E');
+    }
+
+    @Override
+    public void testSucceeded(Description description) {
+    }
+
+    @Override
+    public void testIgnored(Description description) {
+        getWriter().print('I');
+    }
+
+    @Override
+    public void testClassFinishedDelimiter() {
+    }
+
+    @Override
+    public void testClassStartedDelimiter() {
+    }
+
+    @Override
+    public void testStartedDelimiter() {
+    }
+
+    @Override
+    public void testFinishedDelimiter() {
+    }
+
+    public static RunListener createRunListener(GraalJUnitRunListener l) {
+        return new TextListener(l.getWriter()) {
+            private Class<?> lastClass;
+            private boolean failed;
+
+            @Override
+            public final void testStarted(Description description) {
+                Class<?> currentClass = description.getTestClass();
+                if (currentClass != lastClass) {
+                    if (lastClass != null) {
+                        l.testClassFinished(lastClass);
+                        l.testClassFinishedDelimiter();
+                    }
+                    lastClass = currentClass;
+                    l.testClassStarted(currentClass);
+                    l.testClassStartedDelimiter();
+                }
+                failed = false;
+                l.testStarted(description);
+                l.testStartedDelimiter();
+            }
+
+            @Override
+            public final void testFailure(Failure failure) {
+                failed = true;
+                l.testFailed(failure);
+            }
+
+            @Override
+            public final void testFinished(Description description) {
+                // we have to do this because there is no callback for successful tests
+                if (!failed) {
+                    l.testSucceeded(description);
+                }
+                l.testFinished(description);
+                l.testFinishedDelimiter();
+            }
+
+            @Override
+            public void testIgnored(Description description) {
+                l.testStarted(description);
+                l.testStartedDelimiter();
+                l.testIgnored(description);
+                l.testFinished(description);
+                l.testFinishedDelimiter();
+            }
+
+            @Override
+            public void testRunStarted(Description description) {
+                l.testRunStarted(description);
+            }
+
+            @Override
+            public void testRunFinished(Result result) {
+                if (lastClass != null) {
+                    l.testClassFinished(lastClass);
+                }
+                l.testRunFinished(result);
+                super.testRunFinished(result);
+            }
+
+            @Override
+            public void testAssumptionFailure(Failure failure) {
+                l.testAssumptionFailure(failure);
+            }
+
+        };
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalVerboseTextListener.java	Mon May 05 22:18:46 2014 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, 2014, 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.test;
+
+import java.io.*;
+
+import org.junit.internal.*;
+import org.junit.runner.*;
+import org.junit.runner.notification.*;
+
+public class GraalVerboseTextListener extends GraalTextListener {
+
+    public GraalVerboseTextListener(JUnitSystem system) {
+        this(system.out());
+    }
+
+    public GraalVerboseTextListener(PrintStream writer) {
+        super(writer);
+    }
+
+    @Override
+    public void testClassStarted(Class<?> clazz) {
+        getWriter().print(clazz.getName() + " started");
+    }
+
+    @Override
+    public void testClassFinished(Class<?> clazz) {
+        getWriter().print(clazz.getName() + " finished");
+    }
+
+    @Override
+    public void testStarted(Description description) {
+        getWriter().print("  " + description.getMethodName() + ": ");
+    }
+
+    @Override
+    public void testIgnored(Description description) {
+        getWriter().print("Ignored");
+    }
+
+    @Override
+    public void testSucceeded(Description description) {
+        getWriter().print("Passed");
+    }
+
+    @Override
+    public void testFailed(Failure failure) {
+        getWriter().print("FAILED");
+    }
+
+    @Override
+    public void testClassFinishedDelimiter() {
+        getWriter().println();
+    }
+
+    @Override
+    public void testClassStartedDelimiter() {
+        getWriter().println();
+    }
+
+    @Override
+    public void testFinishedDelimiter() {
+        getWriter().println();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/TimingDecorator.java	Mon May 05 22:18:46 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 2014, 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.test;
+
+import org.junit.runner.*;
+
+/**
+ * Timing support for JUnit test runs.
+ */
+public class TimingDecorator extends GraalJUnitRunListenerDecorator {
+
+    private long startTime;
+    private long classStartTime;
+
+    public TimingDecorator(GraalJUnitRunListener l) {
+        super(l);
+    }
+
+    @Override
+    public void testClassStarted(Class<?> clazz) {
+        classStartTime = System.nanoTime();
+        super.testClassStarted(clazz);
+    }
+
+    @Override
+    public void testClassFinished(Class<?> clazz) {
+        long totalTime = System.nanoTime() - classStartTime;
+        super.testClassFinished(clazz);
+        getWriter().print(' ' + valueToString(totalTime));
+    }
+
+    @Override
+    public void testStarted(Description description) {
+        startTime = System.nanoTime();
+        super.testStarted(description);
+    }
+
+    @Override
+    public void testFinished(Description description) {
+        long totalTime = System.nanoTime() - startTime;
+        super.testFinished(description);
+        getWriter().print(" " + valueToString(totalTime));
+    }
+
+    private static String valueToString(long value) {
+        return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10);
+    }
+
+}
--- a/mx/JUnitWrapper.java	Sat May 03 21:46:35 2014 +0200
+++ b/mx/JUnitWrapper.java	Mon May 05 22:18:46 2014 +0200
@@ -27,8 +27,7 @@
  * linux [depending on the settings]: ~2097k)
  * see http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx
  */
-
-import org.junit.runner.*;
+import com.oracle.graal.test.*;
 import java.io.*;
 import java.util.*;
 
@@ -44,6 +43,10 @@
             System.exit(1);
         }
         ArrayList<String> tests = new ArrayList<String>(1000);
+        // add JUnit command line arguments
+        for (int i = 1; i < args.length; i++) {
+            tests.add(args[i]);
+        }
         BufferedReader br = null;
         try {
             br = new BufferedReader(new FileReader(args[0]));
@@ -72,6 +75,6 @@
         } else {
             System.out.printf("executing junit tests now... (%d test classes)\n", strargs.length);
         }
-        JUnitCore.main(strargs);
+        GraalJUnitCore.main(strargs);
     }
 }
--- a/mx/mx_graal.py	Sat May 03 21:46:35 2014 +0200
+++ b/mx/mx_graal.py	Mon May 05 22:18:46 2014 +0200
@@ -946,7 +946,7 @@
         f_testfile.close()
         harness(projectscp, vmArgs)
 
-def _unittest(args, annotations, prefixcp="", whitelist=None):
+def _unittest(args, annotations, prefixcp="", whitelist=None, verbose=False, enable_timing=False):
     mxdir = dirname(__file__)
     name = 'JUnitWrapper'
     javaSource = join(mxdir, name + '.java')
@@ -955,6 +955,12 @@
     if testfile is None:
         (_, testfile) = tempfile.mkstemp(".testclasses", "graal")
         os.close(_)
+    corecp = mx.classpath(['com.oracle.graal.test'])
+    coreArgs = []
+    if verbose:
+        coreArgs.append('-JUnitVerbose')
+    if enable_timing:
+        coreArgs.append('-JUnitEnableTiming')
 
     def harness(projectscp, vmArgs):
         if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource):
@@ -968,9 +974,9 @@
         if len(testclasses) == 1:
             # Execute Junit directly when one test is being run. This simplifies
             # replaying the VM execution in a native debugger (e.g., gdb).
-            vm(prefixArgs + vmArgs + ['-cp', prefixcp + projectscp, 'org.junit.runner.JUnitCore'] + testclasses)
+            vm(prefixArgs + vmArgs + ['-cp', prefixcp + corecp + ':' + projectscp, 'com.oracle.graal.test.GraalJUnitCore'] + coreArgs + testclasses)
         else:
-            vm(prefixArgs + vmArgs + ['-cp', prefixcp + projectscp + os.pathsep + mxdir, name] + [testfile])
+            vm(prefixArgs + vmArgs + ['-cp', prefixcp + corecp + ':' + projectscp + os.pathsep + mxdir, name] + [testfile] + coreArgs)
 
     try:
         _run_tests(args, harness, annotations, testfile, whitelist)
@@ -983,6 +989,8 @@
 
       --whitelist            run only testcases which are included
                              in the given whitelist
+      --verbose              enable verbose JUnit output
+      --enable-timing        enable JUnit test timing
 
     To avoid conflicts with VM options '--' can be used as delimiter.
 
@@ -1020,6 +1028,8 @@
           epilog=_unittestHelpSuffix,
         )
     parser.add_argument('--whitelist', help='run testcases specified in whitelist only', metavar='<path>')
+    parser.add_argument('--verbose', help='enable verbose JUnit output', action='store_true')
+    parser.add_argument('--enable-timing', help='enable JUnit test timing', action='store_true')
 
     ut_args = []
     delimiter = False
@@ -1046,7 +1056,7 @@
         except IOError:
             mx.log('warning: could not read whitelist: ' + parsed_args.whitelist)
 
-    _unittest(args, ['@Test', '@Parameters'], whitelist=whitelist)
+    _unittest(args, ['@Test', '@Parameters'], whitelist=whitelist, verbose=parsed_args.verbose, enable_timing=parsed_args.enable_timing)
 
 def shortunittest(args):
     """alias for 'unittest --whitelist test/whitelist_shortunittest.txt'{0}"""
@@ -1158,12 +1168,12 @@
 
     with VM('server', 'product'):  # hosted mode
         t = Task('UnitTests:hosted-product')
-        unittest([])
+        unittest(['--enable-timing', '--verbose'])
         tasks.append(t.stop())
 
     with VM('server', 'product'):  # hosted mode
         t = Task('UnitTests-BaselineCompiler:hosted-product')
-        unittest(['--whitelist', 'test/whitelist_baseline.txt', '-G:+UseBaselineCompiler'])
+        unittest(['--enable-timing', '--verbose', '--whitelist', 'test/whitelist_baseline.txt', '-G:+UseBaselineCompiler'])
         tasks.append(t.stop())
 
     for vmbuild in ['fastdebug', 'product']:
--- a/mxtool/mx.py	Sat May 03 21:46:35 2014 +0200
+++ b/mxtool/mx.py	Mon May 05 22:18:46 2014 +0200
@@ -1300,8 +1300,21 @@
         time.sleep(delay)
 
 # Makes the current subprocess accessible to the abort() function
-# This is a tuple of the Popen object and args.
-_currentSubprocess = (None, None)
+# This is a list of tuples of the subprocess.Popen or
+# multiprocessing.Process object and args.
+_currentSubprocesses = []
+
+def _addSubprocess(p, args):
+    entry = (p, args)
+    _currentSubprocesses.append(entry)
+    return entry
+
+def _removeSubprocess(entry):
+    if entry and entry in _currentSubprocesses:
+        try:
+            _currentSubprocesses.remove(entry)
+        except:
+            pass
 
 def waitOn(p):
     if get_os() == 'windows':
@@ -1340,8 +1353,7 @@
     if timeout is None and _opts.ptimeout != 0:
         timeout = _opts.ptimeout
 
-    global _currentSubprocess
-
+    sub = None
     try:
         # On Unix, the new subprocess should be in a separate group so that a timeout alarm
         # can use os.killpg() to kill the whole subprocess group
@@ -1359,7 +1371,7 @@
         stdout = out if not callable(out) else subprocess.PIPE
         stderr = err if not callable(err) else subprocess.PIPE
         p = subprocess.Popen(args, cwd=cwd, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn, creationflags=creationflags, env=env)
-        _currentSubprocess = (p, args)
+        sub = _addSubprocess(p, args)
         if callable(out):
             t = Thread(target=redirect, args=(p.stdout, out))
             t.daemon = True  # thread dies with the program
@@ -1382,7 +1394,7 @@
     except KeyboardInterrupt:
         abort(1)
     finally:
-        _currentSubprocess = (None, None)
+        _removeSubprocess(sub)
 
     if retcode and nonZeroIsFatal:
         if _opts.verbose:
@@ -1663,21 +1675,20 @@
     return result
 
 def _send_sigquit():
-    p, args = _currentSubprocess
-
-    def _isJava():
-        if args:
-            name = args[0].split(os.sep)[-1]
-            return name == "java"
-        return False
-
-    if p is not None and _isJava():
-        if get_os() == 'windows':
-            log("mx: implement me! want to send SIGQUIT to my child process")
-        else:
-            _kill_process_group(p.pid, sig=signal.SIGQUIT)
-        time.sleep(0.1)
-
+    for p, args in _currentSubprocesses:
+
+        def _isJava():
+            if args:
+                name = args[0].split(os.sep)[-1]
+                return name == "java"
+            return False
+
+        if p is not None and _isJava():
+            if get_os() == 'windows':
+                log("mx: implement me! want to send SIGQUIT to my child process")
+            else:
+                _kill_process_group(p.pid, sig=signal.SIGQUIT)
+            time.sleep(0.1)
 
 def abort(codeOrMessage):
     """
@@ -1692,12 +1703,14 @@
 
     # import traceback
     # traceback.print_stack()
-    p, _ = _currentSubprocess
-    if p is not None:
-        if get_os() == 'windows':
-            p.kill()
-        else:
-            _kill_process_group(p.pid, signal.SIGKILL)
+    for p, args in _currentSubprocesses:
+        try:
+            if get_os() == 'windows':
+                p.terminate()
+            else:
+                _kill_process_group(p.pid, signal.SIGKILL)
+        except BaseException as e:
+            log('error while killing subprocess {} "{}": {}'.format(p.pid, ' '.join(args), e))
 
     raise SystemExit(codeOrMessage)
 
@@ -1798,7 +1811,7 @@
     return get_env('JDT', join(_primary_suite.mxDir, 'ecj.jar'))
 
 class JavaCompileTask:
-    def __init__(self, args, proj, reason, javafilelist, jdk, outputDir, deps):
+    def __init__(self, args, proj, reason, javafilelist, jdk, outputDir, jdtJar, deps):
         self.proj = proj
         self.reason = reason
         self.javafilelist = javafilelist
@@ -1806,6 +1819,7 @@
         self.jdk = jdk
         self.outputDir = outputDir
         self.done = False
+        self.jdtJar = jdtJar
         self.args = args
 
     def __str__(self):
@@ -1840,20 +1854,8 @@
         cp = classpath(self.proj.name, includeSelf=True)
         toBeDeleted = [argfileName]
 
-        jdtJar = None
-        if not args.javac and args.jdt is not None:
-            if not args.jdt.endswith('.jar'):
-                abort('Path for Eclipse batch compiler does not look like a jar file: ' + args.jdt)
-            jdtJar = args.jdt
-            if not exists(jdtJar):
-                if os.path.abspath(jdtJar) == os.path.abspath(_defaultEcjPath()) and get_env('JDT', None) is None:
-                    # Silently ignore JDT if default location is used but does not exist
-                    jdtJar = None
-                else:
-                    abort('Eclipse batch compiler jar does not exist: ' + args.jdt)
-
         try:
-            if not jdtJar:
+            if not self.jdtJar:
                 mainJava = java()
                 if not args.error_prone:
                     self.logCompilation('javac')
@@ -1878,7 +1880,7 @@
             else:
                 self.logCompilation('JDT')
 
-                jdtVmArgs = ['-Xmx1g', '-jar', jdtJar]
+                jdtVmArgs = ['-Xmx1g', '-jar', self.jdtJar]
 
                 jdtArgs = ['-' + compliance,
                          '-cp', cp, '-g', '-enableJavadoc',
@@ -1946,12 +1948,23 @@
     compilerSelect.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler', default=_defaultEcjPath(), metavar='<path>')
     compilerSelect.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not')
 
-
     if suppliedParser:
         parser.add_argument('remainder', nargs=REMAINDER, metavar='...')
 
     args = parser.parse_args(args)
 
+    jdtJar = None
+    if not args.javac and args.jdt is not None:
+        if not args.jdt.endswith('.jar'):
+            abort('Path for Eclipse batch compiler does not look like a jar file: ' + args.jdt)
+        jdtJar = args.jdt
+        if not exists(jdtJar):
+            if os.path.abspath(jdtJar) == os.path.abspath(_defaultEcjPath()) and get_env('JDT', None) is None:
+                # Silently ignore JDT if default location is used but does not exist
+                jdtJar = None
+            else:
+                abort('Eclipse batch compiler jar does not exist: ' + args.jdt)
+
     if args.only is not None:
         # N.B. This build will not include dependencies including annotation processor dependencies
         sortedProjects = [project(name) for name in args.only.split(',')]
@@ -2087,7 +2100,7 @@
             logv('[no Java sources for {0} - skipping]'.format(p.name))
             continue
 
-        task = JavaCompileTask(args, p, buildReason, javafilelist, jdk, outputDir, taskDeps)
+        task = JavaCompileTask(args, p, buildReason, javafilelist, jdk, outputDir, jdtJar, taskDeps)
 
         if args.parallelize:
             # Best to initialize class paths on main process
@@ -2113,6 +2126,7 @@
                 if t.proc.is_alive():
                     active.append(t)
                 else:
+                    _removeSubprocess(t.sub)
                     if t.proc.exitcode != 0:
                         return ([], joinTasks(tasks))
             return (active, [])
@@ -2126,10 +2140,18 @@
                     task._d = max([remainingDepsDepth(t) for t in incompleteDeps]) + 1
             return task._d
 
+        def compareTasks(t1, t2):
+            d = remainingDepsDepth(t1) - remainingDepsDepth(t2)
+            if d == 0:
+                t1Work = (1 + len(t1.proj.annotation_processors())) * len(t1.javafilelist)
+                t2Work = (1 + len(t2.proj.annotation_processors())) * len(t2.javafilelist)
+                d = t1Work - t2Work
+            return d
+
         def sortWorklist(tasks):
             for t in tasks:
                 t._d = None
-            return sorted(tasks, lambda x, y: remainingDepsDepth(x) - remainingDepsDepth(y))
+            return sorted(tasks, compareTasks)
 
         import multiprocessing
         cpus = multiprocessing.cpu_count()
@@ -2162,6 +2184,7 @@
                     task.proc = multiprocessing.Process(target=executeTask, args=(task,))
                     task.proc.start()
                     active.append(task)
+                    task.sub = _addSubprocess(task.proc, ['JavaCompileTask', str(task)])
                 if len(active) == cpus:
                     break
 
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp	Sat May 03 21:46:35 2014 +0200
+++ b/src/cpu/x86/vm/templateTable_x86_64.cpp	Mon May 05 22:18:46 2014 +0200
@@ -107,10 +107,6 @@
   return Address(rsp,  Interpreter::expr_offset_in_bytes(2));
 }
 
-static inline Address at_tos_p3() {
-  return Address(rsp,  Interpreter::expr_offset_in_bytes(3));
-}
-
 // Condition conversion
 static Assembler::Condition j_not(TemplateTable::Condition cc) {
   switch (cc) {
--- a/src/share/vm/code/nmethod.cpp	Sat May 03 21:46:35 2014 +0200
+++ b/src/share/vm/code/nmethod.cpp	Mon May 05 22:18:46 2014 +0200
@@ -1064,7 +1064,6 @@
 void nmethod::print_on(outputStream* st, const char* msg) const {
   if (st != NULL) {
     ttyLocker ttyl;
-    if (CIPrintCompilerName) st->print("%s:", compiler()->name());
     if (WizardMode) {
       CompileTask::print_compilation(st, this, msg, /*short_form:*/ true);
       st->print_cr(" (" INTPTR_FORMAT ")", this);
--- a/src/share/vm/compiler/compileBroker.cpp	Sat May 03 21:46:35 2014 +0200
+++ b/src/share/vm/compiler/compileBroker.cpp	Mon May 05 22:18:46 2014 +0200
@@ -370,8 +370,6 @@
 // CompileTask::print_line
 void CompileTask::print_line() {
   ttyLocker ttyl;  // keep the following output all in one block
-  // print compiler name if requested
-  if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level()));
   print_compilation();
 }
 
@@ -384,6 +382,8 @@
   if (!short_form) {
     st->print("%7d ", (int) st->time_stamp().milliseconds());  // print timestamp
   }
+  // print compiler name if requested
+  if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level));
   st->print("%4d ", compile_id);    // print compilation number
 
   // For unloaded methods the transition to zombie occurs after the
--- a/src/share/vm/graal/graalCompiler.cpp	Sat May 03 21:46:35 2014 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Mon May 05 22:18:46 2014 +0200
@@ -48,10 +48,6 @@
     return;
   }
 
-  ThreadToNativeFromVM trans(JavaThread::current());
-  JavaThread* THREAD = JavaThread::current();
-  TRACE_graal_1("GraalCompiler::initialize");
-
   uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
   uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024;
   AMD64_ONLY(guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)"));
@@ -71,6 +67,10 @@
   }
 #endif
 
+  ThreadToNativeFromVM trans(JavaThread::current());
+  JavaThread* THREAD = JavaThread::current();
+  TRACE_graal_1("GraalCompiler::initialize");
+
   JNIEnv *env = ((JavaThread *) Thread::current())->jni_environment();
   jclass klass = env->FindClass("com/oracle/graal/hotspot/bridge/CompilerToVMImpl");
   if (klass == NULL) {
--- a/src/share/vm/prims/jvmtiTagMap.cpp	Sat May 03 21:46:35 2014 +0200
+++ b/src/share/vm/prims/jvmtiTagMap.cpp	Mon May 05 22:18:46 2014 +0200
@@ -2790,6 +2790,7 @@
   return true;
 }
 
+#ifdef ASSERT
 // verify that a static oop field is in range
 static inline bool verify_static_oop(InstanceKlass* ik,
                                      oop mirror, int offset) {
@@ -2804,6 +2805,7 @@
     return false;
   }
 }
+#endif // #ifdef ASSERT
 
 // a class references its super class, interfaces, class loader, ...
 // and finally its static fields
--- a/src/share/vm/runtime/mutex.cpp	Sat May 03 21:46:35 2014 +0200
+++ b/src/share/vm/runtime/mutex.cpp	Mon May 05 22:18:46 2014 +0200
@@ -280,16 +280,6 @@
   return x & 0x7FFFFFFF ;
 }
 
-static inline jint MarsagliaXOR (jint * const a) {
-  jint x = *a ;
-  if (x == 0) x = UNS(a)|1 ;
-  x ^= x << 6;
-  x ^= ((unsigned)x) >> 21;
-  x ^= x << 7 ;
-  *a = x ;
-  return x & 0x7FFFFFFF ;
-}
-
 static int Stall (int its) {
   static volatile jint rv = 1 ;
   volatile int OnFrame = 0 ;