changeset 7539:9e2cbc932853

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Wed, 23 Jan 2013 17:25:47 +0100
parents 50793b11b74d (diff) 29b0768b7ba6 (current diff)
children a77f22f2759d
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopyNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java
diffstat 9 files changed, 133 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Wed Jan 23 16:49:55 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Wed Jan 23 17:25:47 2013 +0100
@@ -57,7 +57,7 @@
 
             public void run() {
                 StructuredGraph graph = parse(snippet);
-                new LoweringPhase(runtime(), new Assumptions(false)).apply(graph);
+                new LoweringPhase(null, runtime(), new Assumptions(false)).apply(graph);
                 new FloatingReadPhase().apply(graph);
 
                 ReturnNode returnNode = null;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Jan 23 16:49:55 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Jan 23 17:25:47 2013 +0100
@@ -161,7 +161,7 @@
             new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
         }
 
-        new LoweringPhase(runtime, assumptions).apply(graph);
+        new LoweringPhase(target, runtime, assumptions).apply(graph);
 
         if (GraalOptions.CullFrameStates) {
             new CullFrameStatesPhase().apply(graph);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopyNode.java	Wed Jan 23 16:49:55 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopyNode.java	Wed Jan 23 17:25:47 2013 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.IterableNodeType;
+import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
@@ -34,99 +35,119 @@
 
 public class ArrayCopyNode extends MacroNode implements Virtualizable, IterableNodeType, Lowerable {
 
-    public ArrayCopyNode(InvokeNode invoke) {
+    public ArrayCopyNode(Invoke invoke) {
         super(invoke);
     }
 
-    public ValueNode src() {
+    private ValueNode getSource() {
         return arguments.get(0);
     }
 
-    public ValueNode srcPos() {
+    private ValueNode getSourcePosition() {
         return arguments.get(1);
     }
 
-    public ValueNode dest() {
+    private ValueNode getDestination() {
         return arguments.get(2);
     }
 
-    public ValueNode destPos() {
+    private ValueNode getDestinationPosition() {
         return arguments.get(3);
     }
 
-    public ValueNode length() {
+    private ValueNode getLength() {
         return arguments.get(4);
     }
 
+    private ResolvedJavaMethod selectSnippet(LoweringTool tool) {
+        ResolvedJavaType srcType = getSource().objectStamp().type();
+        ResolvedJavaType destType = getDestination().objectStamp().type();
+
+        if (srcType != null && srcType.isArray() && destType != null && destType.isArray()) {
+            Kind componentKind = srcType.getComponentType().getKind();
+            if (componentKind != Kind.Object) {
+                if (srcType.getComponentType() == destType.getComponentType()) {
+                    return tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind));
+                }
+            } else if (destType.getComponentType().isAssignableFrom(srcType.getComponentType()) && getDestination().objectStamp().isExactType()) {
+                return tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(Kind.Object));
+            }
+        }
+        return null;
+    }
+
+    private static void unrollFixedLengthLoop(StructuredGraph snippetGraph, int length, LoweringTool tool) {
+        snippetGraph.replaceFloating(snippetGraph.getLocal(4), ConstantNode.forInt(length, snippetGraph));
+        // the canonicalization before loop unrolling is needed to propagate the length into additions, etc.
+        new CanonicalizerPhase(tool.getTarget(), tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
+        new LoopFullUnrollPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
+        new CanonicalizerPhase(tool.getTarget(), tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
+    }
+
     @Override
     public void lower(LoweringTool tool) {
-        ResolvedJavaMethod snippetMethod = null;
-        ResolvedJavaType srcType = src().objectStamp().type();
-        ResolvedJavaType destType = dest().objectStamp().type();
-        if (srcType != null && srcType.isArray() && destType != null && destType.isArray()) {
-            Kind componentKind = srcType.getComponentType().getKind();
-            if (componentKind != Kind.Object) {
-                if (srcType.getComponentType() == destType.getComponentType()) {
-                    snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind));
-                }
-            } else if (destType.getComponentType().isAssignableFrom(srcType.getComponentType()) && dest().objectStamp().isExactType()) {
-                snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(Kind.Object));
-            }
-        }
+        ResolvedJavaMethod snippetMethod = selectSnippet(tool);
         if (snippetMethod == null) {
             snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.increaseGenericCallCounterMethod);
             // we will call the generic method. the generic snippet will only increase the counter,
             // not call the actual
             // method. therefore we create a second invoke here.
             ((StructuredGraph) graph()).addAfterFixed(this, createInvoke());
-        } else {
+        }
+        if (Debug.isLogEnabled()) {
             Debug.log("%s > Intrinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType());
         }
 
-        if (snippetMethod != null) {
-            StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class);
-            assert snippetGraph != null : "ArrayCopySnippets should be installed";
-            InvokeNode invoke = replaceWithInvoke();
-            InliningUtil.inline(invoke, snippetGraph, false);
-        } else {
-            super.lower(tool);
+        StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class);
+        assert snippetGraph != null : "ArrayCopySnippets should be installed";
+        if (getLength().isConstant()) {
+            snippetGraph = snippetGraph.copy();
+            unrollFixedLengthLoop(snippetGraph, getLength().asConstant().asInt(), tool);
         }
+        InvokeNode invoke = replaceWithInvoke();
+        InliningUtil.inline(invoke, snippetGraph, false);
+    }
+
+    private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) {
+        return position >= 0 && position + length <= virtualObject.entryCount();
+    }
+
+    private static boolean checkEntryTypes(int srcPos, int length, State srcState, ResolvedJavaType destComponentType) {
+        if (destComponentType.getKind() == Kind.Object) {
+            for (int i = 0; i < length; i++) {
+                if (!destComponentType.isAssignableFrom(srcState.getEntry(srcPos + i).objectStamp().type())) {
+                    return false;
+                }
+            }
+        }
+        return true;
     }
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        if (srcPos().isConstant() && destPos().isConstant() && length().isConstant()) {
-            int srcPos = srcPos().asConstant().asInt();
-            int destPos = destPos().asConstant().asInt();
-            int length = length().asConstant().asInt();
-            State srcState = tool.getObjectState(src());
-            State destState = tool.getObjectState(dest());
+        if (getSourcePosition().isConstant() && getDestinationPosition().isConstant() && getLength().isConstant()) {
+            int srcPos = getSourcePosition().asConstant().asInt();
+            int destPos = getDestinationPosition().asConstant().asInt();
+            int length = getLength().asConstant().asInt();
+            State srcState = tool.getObjectState(getSource());
+            State destState = tool.getObjectState(getDestination());
 
             if (srcState != null && srcState.getState() == EscapeState.Virtual && destState != null && destState.getState() == EscapeState.Virtual) {
                 VirtualObjectNode srcVirtual = srcState.getVirtualObject();
                 VirtualObjectNode destVirtual = destState.getVirtualObject();
-                if (length < 0) {
-                    return;
-                }
-                if (srcPos < 0 || srcPos + length > srcVirtual.entryCount()) {
+                if (length < 0 || !checkBounds(srcPos, length, srcVirtual) || !checkBounds(destPos, length, destVirtual)) {
                     return;
                 }
-                if (destPos < 0 || destPos + length > destVirtual.entryCount()) {
+                if (!checkEntryTypes(srcPos, length, srcState, destVirtual.type().getComponentType())) {
                     return;
                 }
-                ResolvedJavaType destComponentType = destVirtual.type().getComponentType();
-                if (destComponentType.getKind() == Kind.Object) {
-                    for (int i = 0; i < length; i++) {
-                        if (!destComponentType.isAssignableFrom(srcState.getEntry(srcPos + i).objectStamp().javaType(tool.getMetaAccessProvider()))) {
-                            return;
-                        }
-                    }
-                }
                 for (int i = 0; i < length; i++) {
                     tool.setVirtualEntry(destState, destPos + i, srcState.getEntry(srcPos + i));
                 }
                 tool.delete();
-                Debug.log("virtualized arraycopyf(%s, %d, %s, %d, %d)", src(), srcPos, dest(), destPos, length);
+                if (Debug.isLogEnabled()) {
+                    Debug.log("virtualized arraycopyf(%s, %d, %s, %d, %d)", getSource(), srcPos, getDestination(), destPos, length);
+                }
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Wed Jan 23 16:49:55 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Wed Jan 23 17:25:47 2013 +0100
@@ -25,6 +25,7 @@
 import static com.oracle.graal.api.code.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
+import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -89,6 +90,7 @@
         long srcOffset = (long) srcPos * elementSize;
         long destOffset = (long) destPos * elementSize;
         if (src == dest && srcPos < destPos) { // bad aliased case
+            probability(0.1);
             for (long i = byteLength - elementSize; i >= byteLength - nonVectorBytes; i -= elementSize) {
                 UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
             }
@@ -109,13 +111,40 @@
     }
 
     public static void checkInputs(Object src, int srcPos, Object dest, int destPos, int length) {
-        if (src == null || dest == null) {
+        if (src == null) {
+            probability(0.01);
             checkNPECounter.inc();
-            throw new NullPointerException();
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+        }
+        if (dest == null) {
+            probability(0.01);
+            checkNPECounter.inc();
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+        }
+        if (srcPos < 0) {
+            probability(0.01);
+            checkAIOOBECounter.inc();
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > ArrayLengthNode.arrayLength(src) || destPos + length > ArrayLengthNode.arrayLength(dest)) {
+        if (destPos < 0) {
+            probability(0.01);
+            checkAIOOBECounter.inc();
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+        }
+        if (length < 0) {
+            probability(0.01);
             checkAIOOBECounter.inc();
-            throw new ArrayIndexOutOfBoundsException();
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+        }
+        if (srcPos + length > ArrayLengthNode.arrayLength(src)) {
+            probability(0.01);
+            checkAIOOBECounter.inc();
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+        }
+        if (destPos + length > ArrayLengthNode.arrayLength(dest)) {
+            probability(0.01);
+            checkAIOOBECounter.inc();
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
         checkSuccessCounter.inc();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Wed Jan 23 16:49:55 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Wed Jan 23 17:25:47 2013 +0100
@@ -30,6 +30,8 @@
 
 public interface LoweringTool {
 
+    TargetDescription getTarget();
+
     GraalCodeCacheProvider getRuntime();
 
     ValueNode createNullCheckGuard(ValueNode object, long leafGraphId);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Jan 23 16:49:55 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Jan 23 17:25:47 2013 +0100
@@ -225,12 +225,19 @@
                 assert invoke instanceof InvokeNode;
                 FixedWithNextNode macroNode;
                 try {
-                    macroNode = macroNodeClass.getConstructor(InvokeNode.class).newInstance(invoke);
+                    macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke);
                 } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
                     throw new GraalInternalError(e).addContext(invoke.node()).addContext("macroSubstitution", macroNodeClass);
                 }
+                macroNode.setProbability(invoke.node().probability());
                 CallTargetNode callTarget = invoke.callTarget();
-                graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode));
+                if (invoke instanceof InvokeNode) {
+                    graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode));
+                } else {
+                    InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
+                    invokeWithException.killExceptionEdge();
+                    graph.replaceSplitWithFixed(invokeWithException, graph.add(macroNode), invokeWithException.next());
+                }
                 GraphUtil.killWithUnusedFloatingInputs(callTarget);
             } else {
                 StructuredGraph calleeGraph = getIntrinsicGraph(concrete);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Wed Jan 23 16:49:55 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Wed Jan 23 17:25:47 2013 +0100
@@ -43,10 +43,10 @@
 
     final class LoweringToolImpl implements LoweringTool {
 
-        final FixedNode guardAnchor;
-        final NodeBitMap activeGuards;
-        FixedWithNextNode lastFixedNode;
-        ControlFlowGraph cfg;
+        private final FixedNode guardAnchor;
+        private final NodeBitMap activeGuards;
+        private FixedWithNextNode lastFixedNode;
+        private ControlFlowGraph cfg;
 
         public LoweringToolImpl(FixedNode guardAnchor, NodeBitMap activeGuards, ControlFlowGraph cfg) {
             this.guardAnchor = guardAnchor;
@@ -55,6 +55,11 @@
         }
 
         @Override
+        public TargetDescription getTarget() {
+            return target;
+        }
+
+        @Override
         public GraalCodeCacheProvider getRuntime() {
             return runtime;
         }
@@ -101,12 +106,14 @@
         }
     }
 
+    private final TargetDescription target;
     private final GraalCodeCacheProvider runtime;
     private final Assumptions assumptions;
 
     private boolean deferred;
 
-    public LoweringPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) {
+    public LoweringPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions) {
+        this.target = target;
         this.runtime = runtime;
         this.assumptions = assumptions;
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Wed Jan 23 16:49:55 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Wed Jan 23 17:25:47 2013 +0100
@@ -31,6 +31,7 @@
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
@@ -98,6 +99,9 @@
             int opportunities = 0;
             while (current instanceof FixedWithNextNode) {
                 current = ((FixedWithNextNode) current).next();
+                if (current instanceof VirtualizableAllocation) {
+                    return false;
+                }
                 for (PhiNode phi : improvements) {
                     for (Node input : current.inputs()) {
                         if (input == phi) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MacroNode.java	Wed Jan 23 16:49:55 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MacroNode.java	Wed Jan 23 17:25:47 2013 +0100
@@ -33,14 +33,14 @@
 
 public class MacroNode extends AbstractStateSplit implements Lowerable {
 
-    @Input protected NodeInputList<ValueNode> arguments;
+    @Input protected final NodeInputList<ValueNode> arguments;
 
     private final int bci;
     private final ResolvedJavaMethod targetMethod;
     private final JavaType returnType;
 
-    protected MacroNode(InvokeNode invoke) {
-        super(invoke.stamp(), invoke.stateAfter());
+    protected MacroNode(Invoke invoke) {
+        super(invoke.node().stamp(), invoke.stateAfter());
         this.arguments = new NodeInputList<>(this, invoke.methodCallTarget().arguments());
         this.bci = invoke.bci();
         this.targetMethod = invoke.methodCallTarget().targetMethod();