changeset 19239:637ca4d37bca

Extensions and fixes to inline and canonicalize during parsing.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 10 Feb 2015 15:10:46 +0100
parents 1a7b33c96c0d
children afe5d805c88a
files graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java
diffstat 11 files changed, 133 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Tue Feb 10 15:10:46 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	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Feb 10 15:10:46 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	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Tue Feb 10 15:10:46 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	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Tue Feb 10 15:10:46 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/GraphBuilderPhase.java	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Feb 10 15:10:46 2015 +0100
@@ -296,8 +296,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 +523,7 @@
 
             @Override
             protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) {
-                return new SubNode(x, y);
+                return SubNode.create(x, y);
             }
 
             @Override
@@ -532,12 +533,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 +665,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 +861,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 +874,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 +959,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()));
                 }
             }
@@ -1065,6 +1093,10 @@
 
             @Override
             protected 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);
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Tue Feb 10 15:10:46 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/java/ArrayLengthNode.java	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Feb 10 15:10:46 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	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Tue Feb 10 15:10:46 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	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Tue Feb 10 15:10:46 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.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Tue Feb 10 15:10:46 2015 +0100
@@ -66,7 +66,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/substitutions/TruffleGraphBuilderPluginsProvider.java	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java	Tue Feb 10 15:10:46 2015 +0100
@@ -88,7 +88,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;
             }
         });