changeset 19242:51b6ea17aebe

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 10 Feb 2015 20:44:08 +0100
parents 30c8d110b281 (diff) 5ff79efdd040 (current diff)
children 006e321d592b 1b51524ff1c9
files graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java
diffstat 26 files changed, 242 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Tue Feb 10 20:44:08 2015 +0100
@@ -63,6 +63,9 @@
     @Option(help = "Inlines trivial methods during parsing of the bytecodes.", type = OptionType.Expert)
     public static final StableOptionValue<Boolean> InlineDuringParsing = new StableOptionValue<>(false);
 
+    @Option(help = "Traces .", type = OptionType.Debug)
+    public static final StableOptionValue<Boolean> TraceInlineDuringParsing = new StableOptionValue<>(false);
+
     @Option(help = "Maximum depth when inlining during parsing.", type = OptionType.Debug)
     public static final StableOptionValue<Integer> InlineDuringParsingMaxDepth = new StableOptionValue<>(10);
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Feb 10 20:44:08 2015 +0100
@@ -65,6 +65,8 @@
     public static final OptionValue<Boolean> SuppressZeroDebugValues = new OptionValue<>(false);
     @Option(help = "Send Graal IR to dump handlers on error", type = OptionType.Debug)
     public static final OptionValue<Boolean> DumpOnError = new OptionValue<>(false);
+    @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug)
+    public static final OptionValue<Boolean> InterceptBailout = new OptionValue<>(false);
     @Option(help = "Enable more verbose log output when available", type = OptionType.Debug)
     public static final OptionValue<Boolean> LogVerbose = new OptionValue<>(false);
     // @formatter:on
@@ -254,7 +256,7 @@
 
     @Override
     public RuntimeException interceptException(Throwable e) {
-        if (e instanceof BailoutException) {
+        if (e instanceof BailoutException && !InterceptBailout.getValue()) {
             return null;
         }
         Debug.setConfig(Debug.fixedConfig(Debug.DEFAULT_LOG_LEVEL, Debug.DEFAULT_LOG_LEVEL, false, false, false, false, dumpHandlers, verifyHandlers, output));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Tue Feb 10 20:44:08 2015 +0100
@@ -67,7 +67,7 @@
 
     @Override
     protected BytecodeFrame computeFrameForState(FrameState state) {
-        assert state.bci >= 0 || state.bci == BytecodeFrame.BEFORE_BCI;
+        assert state.bci >= 0 || state.bci == BytecodeFrame.BEFORE_BCI : state.bci;
         return super.computeFrameForState(state);
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Tue Feb 10 20:44:08 2015 +0100
@@ -24,6 +24,7 @@
 package com.oracle.graal.java;
 
 import static com.oracle.graal.api.code.TypeCheckHints.*;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
 
 import java.util.*;
@@ -604,9 +605,19 @@
 
     protected abstract T createNewInstance(ResolvedJavaType type, boolean fillContents);
 
+    @SuppressWarnings("unchecked")
     void genNewInstance(int cpi) {
         JavaType type = lookupType(cpi, NEW);
         if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) {
+            ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes();
+            if (skippedExceptionTypes != null) {
+                for (ResolvedJavaType exceptionType : skippedExceptionTypes) {
+                    if (exceptionType.isAssignableFrom((ResolvedJavaType) type)) {
+                        append((T) new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter));
+                        return;
+                    }
+                }
+            }
             frameState.apush(append(createNewInstance((ResolvedJavaType) type, true)));
         } else {
             handleUnresolvedNewInstance(type);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Feb 10 20:44:08 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
@@ -296,8 +299,9 @@
                     processBlock(this, returnBlock);
                     processBlock(this, unwindBlock);
 
-                    Debug.dump(currentGraph, "After bytecode parsing");
-
+                    if (Debug.isDumpEnabled()) {
+                        Debug.dump(currentGraph, "Bytecodes parsed: " + method.getDeclaringClass().getUnqualifiedName() + "." + method.getName());
+                    }
                 }
             }
 
@@ -522,7 +526,7 @@
 
             @Override
             protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) {
-                return new SubNode(x, y);
+                return SubNode.create(x, y);
             }
 
             @Override
@@ -532,12 +536,12 @@
 
             @Override
             protected ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new AddNode(x, y);
+                return AddNode.create(x, y);
             }
 
             @Override
             protected ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new SubNode(x, y);
+                return SubNode.create(x, y);
             }
 
             @Override
@@ -664,12 +668,12 @@
 
             @Override
             protected ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck) {
-                return new CheckCastNode(type, object, profileForTypeCheck, forStoreCheck);
+                return CheckCastNode.create(type, object, profileForTypeCheck, forStoreCheck);
             }
 
             @Override
             protected ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck) {
-                return new InstanceOfNode(type, object, profileForTypeCheck);
+                return InstanceOfNode.create(type, object, profileForTypeCheck);
             }
 
             @Override
@@ -860,6 +864,12 @@
 
                 if (graphBuilderPlugins != null) {
                     if (tryUsingInvocationPlugin(args, targetMethod, resultType)) {
+                        if (GraalOptions.TraceInlineDuringParsing.getValue()) {
+                            for (int i = 0; i < this.currentDepth; ++i) {
+                                TTY.print(' ');
+                            }
+                            TTY.println("Used invocation plugin for " + targetMethod);
+                        }
                         return;
                     }
                 }
@@ -867,8 +877,20 @@
                 InlineInvokePlugin inlineInvokePlugin = graphBuilderConfig.getInlineInvokePlugin();
                 if (inlineInvokePlugin != null && invokeKind.isDirect() && targetMethod.canBeInlined() && targetMethod.hasBytecodes() &&
                                 inlineInvokePlugin.shouldInlineInvoke(targetMethod, currentDepth)) {
+                    if (GraalOptions.TraceInlineDuringParsing.getValue()) {
+                        int bci = this.bci();
+                        for (int i = 0; i < this.currentDepth; ++i) {
+                            TTY.print(' ');
+                        }
+                        StackTraceElement stackTraceElement = this.method.asStackTraceElement(bci);
+                        String s = String.format("%s (%s:%d)", method.getName(), stackTraceElement.getFileName(), stackTraceElement.getLineNumber());
+                        TTY.print(s);
+                        TTY.println(" inlining call " + targetMethod.getName());
+                    }
                     parseAndInlineCallee(targetMethod, args);
                     return;
+                } else {
+                    // System.out.println("Could not inline invoke " + targetMethod);
                 }
 
                 MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType));
@@ -940,6 +962,15 @@
                 if (calleeBeforeUnwindNode != null) {
                     ValueNode calleeUnwindValue = parser.getUnwindValue();
                     assert calleeUnwindValue != null;
+                    if (calleeBeforeUnwindNode instanceof AbstractMergeNode) {
+                        AbstractMergeNode mergeNode = (AbstractMergeNode) calleeBeforeUnwindNode;
+                        HIRFrameStateBuilder dispatchState = frameState.copy();
+                        dispatchState.clearStack();
+                        dispatchState.apush(calleeUnwindValue);
+                        dispatchState.setRethrowException(true);
+                        mergeNode.setStateAfter(dispatchState.create(bci()));
+
+                    }
                     calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci()));
                 }
             }
@@ -1063,8 +1094,13 @@
                 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;
+                }
                 if (v instanceof ControlSinkNode) {
                     return append((ControlSinkNode) v);
                 }
@@ -1675,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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java	Tue Feb 10 20:44:08 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/calc/SubNode.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Tue Feb 10 20:44:08 2015 +0100
@@ -25,7 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Sub;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -40,6 +40,17 @@
         super(ArithmeticOpTable::getSub, x, y);
     }
 
+    public static ValueNode create(ValueNode x, ValueNode y) {
+        BinaryOp<Sub> op = ArithmeticOpTable.forStamp(x.stamp()).getSub();
+        Stamp stamp = op.foldStamp(x.stamp(), y.stamp());
+        ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp);
+        if (tryConstantFold != null) {
+            return tryConstantFold;
+        } else {
+            return new SubNode(x, y);
+        }
+    }
+
     @SuppressWarnings("hiding")
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Tue Feb 10 20:44:08 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.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Feb 10 20:44:08 2015 +0100
@@ -52,6 +52,11 @@
     }
 
     public static ValueNode create(ValueNode forValue, ConstantReflectionProvider constantReflection) {
+        if (forValue instanceof NewArrayNode) {
+            NewArrayNode newArray = (NewArrayNode) forValue;
+            return newArray.length();
+        }
+
         ValueNode length = readArrayLengthConstant(forValue, constantReflection);
         if (length != null) {
             return length;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Tue Feb 10 20:44:08 2015 +0100
@@ -62,6 +62,14 @@
         this.forStoreCheck = forStoreCheck;
     }
 
+    public static ValueNode create(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) {
+        ValueNode synonym = findSynonym(type, object);
+        if (synonym != null) {
+            return synonym;
+        }
+        return new CheckCastNode(type, object, profile, forStoreCheck);
+    }
+
     public boolean isForStoreCheck() {
         return forStoreCheck;
     }
@@ -144,15 +152,9 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        ResolvedJavaType objectType = StampTool.typeOrNull(object());
-        if (objectType != null && type.isAssignableFrom(objectType)) {
-            // we don't have to check for null types here because they will also pass the
-            // checkcast.
-            return object();
-        }
-
-        if (StampTool.isPointerAlwaysNull(object())) {
-            return object();
+        ValueNode synonym = findSynonym(type, object());
+        if (synonym != null) {
+            return synonym;
         }
 
         if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) {
@@ -167,6 +169,20 @@
         return this;
     }
 
+    private static ValueNode findSynonym(ResolvedJavaType type, ValueNode object) {
+        ResolvedJavaType objectType = StampTool.typeOrNull(object);
+        if (objectType != null && type.isAssignableFrom(objectType)) {
+            // we don't have to check for null types here because they will also pass the
+            // checkcast.
+            return object;
+        }
+
+        if (StampTool.isPointerAlwaysNull(object)) {
+            return object;
+        }
+        return null;
+    }
+
     @Override
     public void simplify(SimplifierTool tool) {
         // if the previous node is also a checkcast, with a less precise and compatible type,
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Tue Feb 10 20:44:08 2015 +0100
@@ -46,6 +46,16 @@
         assert type != null;
     }
 
+    public static LogicNode create(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) {
+        ObjectStamp objectStamp = (ObjectStamp) object.stamp();
+        LogicNode constantValue = findSynonym(type, objectStamp.type(), objectStamp.nonNull(), objectStamp.isExactType());
+        if (constantValue != null) {
+            return constantValue;
+        } else {
+            return new InstanceOfNode(type, object, profile);
+        }
+    }
+
     @Override
     public void lower(LoweringTool tool) {
         tool.getLowerer().lower(this, tool);
@@ -82,7 +92,25 @@
     }
 
     private ValueNode checkInstanceOf(ValueNode forValue, ResolvedJavaType inputType, boolean nonNull, boolean exactType) {
-        boolean subType = type().isAssignableFrom(inputType);
+        ValueNode result = findSynonym(type(), inputType, nonNull, exactType);
+        if (result != null) {
+            return result;
+        }
+        if (type().isAssignableFrom(inputType)) {
+            if (!nonNull) {
+                // the instanceof matches if the object is non-null, so return true
+                // depending on the null-ness.
+                return new LogicNegationNode(new IsNullNode(forValue));
+            }
+        }
+        return null;
+    }
+
+    public static LogicNode findSynonym(ResolvedJavaType type, ResolvedJavaType inputType, boolean nonNull, boolean exactType) {
+        if (inputType == null) {
+            return null;
+        }
+        boolean subType = type.isAssignableFrom(inputType);
         if (subType) {
             if (nonNull) {
                 // the instanceOf matches, so return true
@@ -95,21 +123,14 @@
                 // also make the check fail.
                 return LogicConstantNode.contradiction();
             } else {
-                boolean superType = inputType.isAssignableFrom(type());
-                if (!superType && !inputType.isInterface() && !type().isInterface()) {
+                boolean superType = inputType.isAssignableFrom(type);
+                if (!superType && !inputType.isInterface() && !type.isInterface()) {
                     return LogicConstantNode.contradiction();
                 }
                 // since the subtype comparison was only performed on a declared type we don't
                 // really know if it might be true at run time...
             }
         }
-        if (type().isAssignableFrom(inputType)) {
-            if (!nonNull) {
-                // the instanceof matches if the object is non-null, so return true
-                // depending on the null-ness.
-                return new LogicNegationNode(new IsNullNode(forValue));
-            }
-        }
         return null;
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Feb 10 20:44:08 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/TruffleCompilerImpl.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Tue Feb 10 20:44:08 2015 +0100
@@ -68,7 +68,8 @@
     private final TruffleCache truffleCache;
     private final GraalTruffleCompilationListener compilationNotify;
 
-    private static final Class<?>[] SKIPPED_EXCEPTION_CLASSES = new Class[]{UnexpectedResultException.class, SlowPathException.class, ArithmeticException.class, IllegalArgumentException.class};
+    private static final Class<?>[] SKIPPED_EXCEPTION_CLASSES = new Class[]{UnexpectedResultException.class, SlowPathException.class, ArithmeticException.class, IllegalArgumentException.class,
+                    VirtualMachineError.class, ClassCastException.class};
 
     public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability,
                     OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Tue Feb 10 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java	Tue Feb 10 20:44:08 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 16:03:45 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java	Tue Feb 10 20:44:08 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)));
@@ -87,7 +114,7 @@
         });
         r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() {
             public boolean apply(GraphBuilderContext builder, ValueNode probability, ValueNode condition) {
-                builder.append(new BranchProbabilityNode(probability, condition));
+                builder.push(Kind.Boolean.getStackKind(), builder.append(new BranchProbabilityNode(probability, condition)));
                 return true;
             }
         });
@@ -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;
             }