changeset 19241:30c8d110b281

More Truffle graph builder plugins and parse time canonicalizations.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 10 Feb 2015 20:43:48 +0100
parents afe5d805c88a
children 51b6ea17aebe
files graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java
diffstat 17 files changed, 109 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java	Tue Feb 10 20:43:48 2015 +0100
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -41,6 +42,8 @@
 
     <T extends FloatingNode> T append(T value);
 
+    <T extends ValueNode> T append(T value);
+
     StampProvider getStampProvider();
 
     MetaAccessProvider getMetaAccess();
@@ -49,6 +52,8 @@
 
     ConstantReflectionProvider getConstantReflection();
 
+    SnippetReflectionProvider getSnippetReflection();
+
     void push(Kind kind, ValueNode value);
 
     /**
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Feb 10 20:43:48 2015 +0100
@@ -32,6 +32,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
@@ -77,7 +78,7 @@
 
     @Override
     protected void run(StructuredGraph graph, HighTierContext context) {
-        new Instance(context.getMetaAccess(), context.getStampProvider(), context.getAssumptions(), context.getConstantReflection(), graphBuilderConfig, graphBuilderPlugins,
+        new Instance(context.getMetaAccess(), context.getStampProvider(), context.getAssumptions(), null, context.getConstantReflection(), graphBuilderConfig, graphBuilderPlugins,
                         context.getOptimisticOptimizations()).run(graph);
     }
 
@@ -103,6 +104,7 @@
         private final StampProvider stampProvider;
         private final Assumptions assumptions;
         private final ConstantReflectionProvider constantReflection;
+        private final SnippetReflectionProvider snippetReflectionProvider;
 
         /**
          * Gets the graph being processed by this builder.
@@ -111,8 +113,8 @@
             return currentGraph;
         }
 
-        public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflection,
-                        GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, OptimisticOptimizations optimisticOpts) {
+        public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, SnippetReflectionProvider snippetReflectionProvider,
+                        ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, OptimisticOptimizations optimisticOpts) {
             this.graphBuilderConfig = graphBuilderConfig;
             this.optimisticOpts = optimisticOpts;
             this.metaAccess = metaAccess;
@@ -120,12 +122,13 @@
             this.assumptions = assumptions;
             this.graphBuilderPlugins = graphBuilderPlugins;
             this.constantReflection = constantReflection;
+            this.snippetReflectionProvider = snippetReflectionProvider;
             assert metaAccess != null;
         }
 
         public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflection,
                         GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
-            this(metaAccess, stampProvider, assumptions, constantReflection, graphBuilderConfig, null, optimisticOpts);
+            this(metaAccess, stampProvider, assumptions, null, constantReflection, graphBuilderConfig, null, optimisticOpts);
         }
 
         @Override
@@ -1091,8 +1094,9 @@
                 return ConstantNode.forConstant(constant, metaAccess, currentGraph);
             }
 
+            @SuppressWarnings("unchecked")
             @Override
-            protected ValueNode append(ValueNode v) {
+            public ValueNode append(ValueNode v) {
                 if (v.graph() != null) {
                     // This node was already appended to the graph.
                     return v;
@@ -1707,6 +1711,10 @@
                 return constantReflection;
             }
 
+            public SnippetReflectionProvider getSnippetReflection() {
+                return snippetReflectionProvider;
+            }
+
         }
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java	Tue Feb 10 20:43:48 2015 +0100
@@ -88,7 +88,8 @@
         }
 
         public boolean apply(GraphBuilderContext builder, ValueNode value) {
-            builder.push(kind.getStackKind(), builder.append(new UnboxNode(nullCheckedValue(builder, value), kind)));
+            ValueNode valueNode = UnboxNode.create(builder.getMetaAccess(), builder.getConstantReflection(), nullCheckedValue(builder, value), kind);
+            builder.push(kind.getStackKind(), builder.append(valueNode));
             return true;
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Tue Feb 10 20:43:48 2015 +0100
@@ -52,9 +52,7 @@
     }
 
     public PiNode(ValueNode object, Stamp stamp) {
-        super(stamp);
-        this.piStamp = stamp;
-        this.object = object;
+        this(object, stamp, null);
     }
 
     public PiNode(ValueNode object, Stamp stamp, ValueNode anchor) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Tue Feb 10 20:43:48 2015 +0100
@@ -165,32 +165,32 @@
         return null;
     }
 
-    public static CompareNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) {
-        return graph.unique(createCompareNode(condition, x, y));
+    public static LogicNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) {
+        return graph.unique(createCompareNode(condition, x, y, constantReflection));
     }
 
-    public static CompareNode createCompareNode(Condition condition, ValueNode x, ValueNode y) {
+    public static LogicNode createCompareNode(Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) {
         assert x.getKind() == y.getKind();
         assert condition.isCanonical() : "condition is not canonical: " + condition;
         assert !x.getKind().isNumericFloat();
 
-        CompareNode comparison;
+        LogicNode comparison;
         if (condition == Condition.EQ) {
             if (x.stamp() instanceof AbstractObjectStamp) {
-                comparison = new ObjectEqualsNode(x, y);
+                comparison = ObjectEqualsNode.create(x, y, constantReflection);
             } else if (x.stamp() instanceof AbstractPointerStamp) {
                 comparison = new PointerEqualsNode(x, y);
             } else {
                 assert x.getKind().isNumericInteger();
-                comparison = new IntegerEqualsNode(x, y);
+                comparison = IntegerEqualsNode.create(x, y, constantReflection);
             }
         } else if (condition == Condition.LT) {
             assert x.getKind().isNumericInteger();
-            comparison = new IntegerLessThanNode(x, y);
+            comparison = IntegerLessThanNode.create(x, y, constantReflection);
         } else {
             assert condition == Condition.BT;
             assert x.getKind().isNumericInteger();
-            comparison = new IntegerBelowNode(x, y);
+            comparison = IntegerBelowNode.create(x, y, constantReflection);
         }
 
         return comparison;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Tue Feb 10 20:43:48 2015 +0100
@@ -120,7 +120,7 @@
     }
 
     public ConditionalNode(@InjectedNodeParameter StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) {
-        this(createCompareNode(graph, condition, x, y));
+        this(createCompareNode(graph, condition, x, y, null));
     }
 
     public ConditionalNode(ValueNode type, ValueNode object) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java	Tue Feb 10 20:43:48 2015 +0100
@@ -64,7 +64,7 @@
         }
         if (forX.isConstant() && forX.asJavaConstant().asLong() == 0) {
             // 0 |<| y is the same as 0 != y
-            return new LogicNegationNode(CompareNode.createCompareNode(Condition.EQ, forX, forY));
+            return new LogicNegationNode(CompareNode.createCompareNode(Condition.EQ, forX, forY, tool.getConstantReflection()));
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Tue Feb 10 20:43:48 2015 +0100
@@ -31,15 +31,23 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public class UnboxNode extends UnaryNode implements Virtualizable, Lowerable {
+public final class UnboxNode extends UnaryNode implements Virtualizable, Lowerable {
 
     protected final Kind boxingKind;
 
-    public UnboxNode(ValueNode value, Kind boxingKind) {
+    protected UnboxNode(ValueNode value, Kind boxingKind) {
         super(StampFactory.forKind(boxingKind.getStackKind()), value);
         this.boxingKind = boxingKind;
     }
 
+    public static ValueNode create(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ValueNode value, Kind boxingKind) {
+        ValueNode synonym = findSynonym(metaAccess, constantReflection, value, boxingKind);
+        if (synonym != null) {
+            return synonym;
+        }
+        return new UnboxNode(value, boxingKind);
+    }
+
     public Kind getBoxingKind() {
         return boxingKind;
     }
@@ -63,11 +71,19 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        ValueNode synonym = findSynonym(tool.getMetaAccess(), tool.getConstantReflection(), forValue, boxingKind);
+        if (synonym != null) {
+            return synonym;
+        }
+        return this;
+    }
+
+    private static ValueNode findSynonym(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ValueNode forValue, Kind boxingKind) {
         if (forValue.isConstant()) {
             JavaConstant constant = forValue.asJavaConstant();
-            JavaConstant unboxed = tool.getConstantReflection().unboxPrimitive(constant);
+            JavaConstant unboxed = constantReflection.unboxPrimitive(constant);
             if (unboxed != null && unboxed.getKind() == boxingKind) {
-                return ConstantNode.forConstant(unboxed, tool.getMetaAccess());
+                return ConstantNode.forConstant(unboxed, metaAccess);
             }
         } else if (forValue instanceof BoxNode) {
             BoxNode box = (BoxNode) forValue;
@@ -75,7 +91,7 @@
                 return box.getValue();
             }
         }
-        return this;
+        return null;
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Tue Feb 10 20:43:48 2015 +0100
@@ -376,7 +376,7 @@
             FixedNode lastSucc = successors[concretes.size()];
             for (int i = concretes.size() - 1; i >= 0; --i) {
                 LoadMethodNode method = graph.add(new LoadMethodNode(stampProvider.createMethodStamp(), concretes.get(i), receiverType, hub));
-                CompareNode methodCheck = CompareNode.createCompareNode(graph, Condition.EQ, method, constantMethods[i]);
+                LogicNode methodCheck = CompareNode.createCompareNode(graph, Condition.EQ, method, constantMethods[i], null);
                 IfNode ifNode = graph.add(new IfNode(methodCheck, successors[i], lastSucc, probability[i]));
                 method.setNext(ifNode);
                 lastSucc = method;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java	Tue Feb 10 20:43:48 2015 +0100
@@ -106,7 +106,7 @@
         LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver));
         ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(), type.getObjectHub(), providers.getMetaAccess(), graph);
 
-        CompareNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub);
+        LogicNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub, providers.getConstantReflection());
         FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
         assert invoke.predecessor() != null;
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Tue Feb 10 20:43:48 2015 +0100
@@ -112,7 +112,7 @@
     public static final class Instantiation {
 
         private ValueNode result;
-        private CompareNode condition;
+        private LogicNode condition;
         private ValueNode trueValue;
         private ValueNode falseValue;
 
@@ -141,9 +141,9 @@
                 assert testValue.isConstant();
                 return LogicConstantNode.forBoolean(result.asConstant().equals(testValue.asConstant()), result.graph());
             }
-            if (condition == null || condition.getY() != testValue) {
+            if (condition == null || (!(condition instanceof CompareNode)) || ((CompareNode) condition).getY() != testValue) {
                 // Re-use previously generated condition if the trueValue for the test is the same
-                condition = createCompareNode(result.graph(), Condition.EQ, result, testValue);
+                condition = createCompareNode(result.graph(), Condition.EQ, result, testValue, null);
             }
             return condition;
         }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Tue Feb 10 20:43:48 2015 +0100
@@ -30,6 +30,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.CompilerDirectives.*;
 import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
@@ -50,7 +51,8 @@
 
     @Override
     public void check() throws InvalidAssumptionException {
-        if (!isValid) {
+        if (!this.isValid()) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
             throw new InvalidAssumptionException();
         }
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Feb 10 20:43:48 2015 +0100
@@ -219,8 +219,10 @@
             p.registerPlugins(providers.getMetaAccess(), plugins);
         }
         TruffleGraphBuilderPlugins.registerPlugins(providers.getMetaAccess(), plugins);
-        new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), providers.getConstantReflection(), newConfig, plugins,
+        long ms = System.currentTimeMillis();
+        new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(true), this.snippetReflection, providers.getConstantReflection(), newConfig, plugins,
                         TruffleCompilerImpl.Optimizations).apply(graph);
+        System.out.println("# ms: " + (System.currentTimeMillis() - ms));
         Debug.dump(graph, "After FastPE");
 
         // Do single partial escape and canonicalization pass.
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Tue Feb 10 20:43:48 2015 +0100
@@ -88,7 +88,7 @@
 
     @Override
     public void lower(LoweringTool tool) {
-        CompareNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, graph()));
+        LogicNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, graph()), tool.getConstantReflection());
         LocationIdentity locationIdentity;
         if (!location.isConstant() || location.isNullConstant()) {
             locationIdentity = LocationIdentity.ANY_LOCATION;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Tue Feb 10 20:43:48 2015 +0100
@@ -63,7 +63,7 @@
             } else {
                 locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant());
             }
-            CompareNode compare = CompareNode.createCompareNode(Condition.EQ, conditionArgument, ConstantNode.forBoolean(true));
+            LogicNode compare = CompareNode.createCompareNode(Condition.EQ, conditionArgument, ConstantNode.forBoolean(true), tool.getConstantReflection());
             Kind returnKind = this.getTargetMethod().getSignature().getReturnKind();
             return new UnsafeLoadNode(objectArgument, offsetArgument, returnKind, locationIdentity, compare);
         }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java	Tue Feb 10 20:43:48 2015 +0100
@@ -64,7 +64,7 @@
             } else {
                 Stamp piStamp = StampFactory.declaredTrusted(lookupJavaType, nonNullArgument.asJavaConstant().asInt() != 0);
                 ConditionAnchorNode valueAnchorNode = graph().add(
-                                new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph()))));
+                                new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph()), tool.getConstantReflection())));
                 PiNode piCast = graph().unique(new PiNode(objectArgument, piStamp, valueAnchorNode));
                 replaceAtUsages(piCast);
                 graph().replaceFixedWithFixed(this, valueAnchorNode);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java	Tue Feb 10 15:10:56 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java	Tue Feb 10 20:43:48 2015 +0100
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.java.*;
@@ -39,6 +40,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.truffle.*;
 import com.oracle.graal.truffle.nodes.*;
+import com.oracle.graal.truffle.nodes.arithmetic.*;
 import com.oracle.graal.truffle.nodes.frame.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
@@ -49,8 +51,33 @@
 public class TruffleGraphBuilderPlugins {
     public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
 
+        // OptimizedAssumption.class
+        Registration r = new Registration(plugins, metaAccess, OptimizedAssumption.class);
+        r.register1("isValid", Receiver.class, new InvocationPlugin() {
+            public boolean apply(GraphBuilderContext builder, ValueNode arg) {
+                if (arg.isConstant()) {
+                    Constant constant = arg.asConstant();
+                    OptimizedAssumption assumption = builder.getSnippetReflection().asObject(OptimizedAssumption.class, (JavaConstant) constant);
+                    builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(assumption.isValid())));
+                    builder.getAssumptions().record(new AssumptionValidAssumption(assumption));
+                } else {
+                    throw new BailoutException("assumption could not be reduced to a constant");
+                }
+                return true;
+            }
+        });
+
+        // ExactMath.class
+        r = new Registration(plugins, metaAccess, ExactMath.class);
+        r.register2("addExact", Integer.TYPE, Integer.TYPE, new InvocationPlugin() {
+            public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
+                builder.push(Kind.Int.getStackKind(), builder.append(new IntegerAddExactNode(x, y)));
+                return true;
+            }
+        });
+
         // CompilerDirectives.class
-        Registration r = new Registration(plugins, metaAccess, CompilerDirectives.class);
+        r = new Registration(plugins, metaAccess, CompilerDirectives.class);
         r.register0("inInterpreter", new InvocationPlugin() {
             public boolean apply(GraphBuilderContext builder) {
                 builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(false)));
@@ -134,6 +161,7 @@
         });
         r.register4("unsafeCast", Object.class, Class.class, boolean.class, boolean.class, new InvocationPlugin() {
             public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode clazz, ValueNode condition, ValueNode nonNull) {
+                System.out.println("unsafe cast with cond: " + condition + " clazz: " + clazz + " nonNull: " + nonNull);
                 if (clazz.isConstant() && nonNull.isConstant()) {
                     ConstantReflectionProvider constantReflection = builder.getConstantReflection();
                     ResolvedJavaType javaType = constantReflection.asJavaType(clazz.asConstant());
@@ -141,15 +169,24 @@
                         builder.push(Kind.Object, object);
                     } else {
                         Stamp piStamp = StampFactory.declaredTrusted(javaType, nonNull.asJavaConstant().asInt() != 0);
-                        ConditionAnchorNode valueAnchorNode = builder.append(new ConditionAnchorNode(CompareNode.createCompareNode(object.graph(), Condition.EQ, condition,
-                                        ConstantNode.forBoolean(true, object.graph()))));
+                        LogicNode compareNode = CompareNode.createCompareNode(object.graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), constantReflection);
+                        boolean skipAnchor = false;
+                        if (compareNode instanceof LogicConstantNode) {
+                            LogicConstantNode logicConstantNode = (LogicConstantNode) compareNode;
+                            if (logicConstantNode.getValue()) {
+                                skipAnchor = true;
+                            }
+                        }
+                        ConditionAnchorNode valueAnchorNode = null;
+                        if (!skipAnchor) {
+                            valueAnchorNode = builder.append(new ConditionAnchorNode(compareNode));
+                        }
                         PiNode piCast = builder.append(new PiNode(object, piStamp, valueAnchorNode));
                         builder.push(Kind.Object, piCast);
                     }
                     return true;
                 }
-                // TODO: should we throw GraalInternalError.shouldNotReachHere() here?
-                return false;
+                throw GraalInternalError.shouldNotReachHere("unsafeCast arguments could not reduce to a constant: " + clazz + ", " + nonNull);
             }
         });
         for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}) {
@@ -178,7 +215,7 @@
                 } else {
                     locationIdentity = ObjectLocationIdentity.create(location.asJavaConstant());
                 }
-                CompareNode compare = builder.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph())));
+                LogicNode compare = builder.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), builder.getConstantReflection()));
                 builder.push(returnKind.getStackKind(), builder.append(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare)));
                 return true;
             }