changeset 5255:38feba3e8526

separated safepoints out of LoopEndNodes into SafepointNodes
author Doug Simon <doug.simon@oracle.com>
date Thu, 19 Apr 2012 22:57:53 +0200
parents 9c2b6cc9de45
children 1e153fdac9fb a549662f6c6f
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/SafepointPollingEliminationPhase.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java
diffstat 7 files changed, 94 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/SafepointPollingEliminationPhase.java	Thu Apr 19 22:45:50 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/SafepointPollingEliminationPhase.java	Thu Apr 19 22:57:53 2012 +0200
@@ -26,16 +26,23 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.util.*;
 
+/**
+ * Removes safepoints from loops that include calls.
+ * This optimization is conservative; it does not try to remove safepoints from outer loops.
+ */
 public class SafepointPollingEliminationPhase extends Phase {
 
     @Override
     protected void run(StructuredGraph graph) {
-        for (LoopEndNode loopEnd : graph.getNodes(LoopEndNode.class)) {
-            NodeIterable<FixedNode> it = NodeIterators.dominators(loopEnd).until(loopEnd.loopBegin());
-            for (FixedNode n : it) {
-                if (n instanceof Invoke) {
-                    loopEnd.setSafepointPolling(false);
-                    break;
+        for (SafepointNode safepoint : graph.getNodes(SafepointNode.class)) {
+            LoopEndNode loopEnd = safepoint.loopEnd();
+            if (loopEnd != null) {
+                NodeIterable<FixedNode> it = NodeIterators.dominators(loopEnd).until(loopEnd.loopBegin());
+                for (FixedNode n : it) {
+                    if (n instanceof Invoke) {
+                        graph.removeFixed(safepoint);
+                        break;
+                    }
                 }
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Thu Apr 19 22:45:50 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Thu Apr 19 22:57:53 2012 +0200
@@ -59,15 +59,13 @@
     @Override
     public LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, RiResolvedMethod method, LIR lir, RiXirGenerator xir) {
         return new AMD64LIRGenerator(graph, runtime, target, frameMap, method, lir, xir) {
+
             @Override
-            public void visitLoopEnd(LoopEndNode x) {
-                if (GraalOptions.GenLoopSafepoints && x.hasSafepointPolling()) {
-                    LIRDebugInfo info = state();
-                    if (!info.topFrame.method.noSafepointPolls()) {
-                        append(new AMD64SafepointOp(info, ((HotSpotRuntime) runtime).config));
-                    }
-                }
+            public void visitSafepointNode(SafepointNode i) {
+                LIRDebugInfo info = state();
+                append(new AMD64SafepointOp(info, ((HotSpotRuntime) runtime).config));
             }
+
             @Override
             public void visitExceptionObject(ExceptionObjectNode x) {
                 HotSpotVMConfig config = ((HotSpotRuntime) runtime).config;
@@ -181,10 +179,10 @@
 
         // Emit the prefix
         tasm.recordMark(MARK_OSR_ENTRY);
-        tasm.recordMark(MARK_UNVERIFIED_ENTRY);
 
         boolean isStatic = Modifier.isStatic(method.accessFlags());
         if (!isStatic) {
+            tasm.recordMark(MARK_UNVERIFIED_ENTRY);
             CiCallingConvention cc = regConfig.getCallingConvention(JavaCallee, new CiKind[] {CiKind.Object}, target, false);
             CiRegister inlineCacheKlass = rax; // see definition of IC_Klass in c1_LIRAssembler_x86.cpp
             CiRegister receiver = asRegister(cc.locations[0]);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Apr 19 22:45:50 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Apr 19 22:57:53 2012 +0200
@@ -194,6 +194,14 @@
             currentGraph.removeFixed(n);
         }
 
+        // Add safepoints to loop ends
+        if (GraalOptions.GenLoopSafepoints) {
+            for (LoopEndNode loopEnd : currentGraph.getNodes(LoopEndNode.class)) {
+                SafepointNode safepoint = currentGraph.add(new SafepointNode(loopEnd));
+                currentGraph.addBeforeFixed(loopEnd, safepoint);
+            }
+        }
+
         // remove dead FrameStates
         for (Node n : currentGraph.getNodes(FrameState.class)) {
             if (n.usages().size() == 0 && n.predecessor() == null) {
@@ -1210,7 +1218,7 @@
         }
     }
 
-    private Target checkLoopExit(FixedNode traget, Block targetBlock, FrameStateBuilder state) {
+    private Target checkLoopExit(FixedNode target, Block targetBlock, FrameStateBuilder state) {
         if (currentBlock != null) {
             long exits = currentBlock.loops & ~targetBlock.loops;
             if (exits != 0) {
@@ -1250,16 +1258,16 @@
                         firstLoopExit = loopExit;
                     }
                     lastLoopExit = loopExit;
-                    Debug.log("Traget %s (%s) Exits %s, scanning framestates...", targetBlock, traget, loop);
+                    Debug.log("Target %s (%s) Exits %s, scanning framestates...", targetBlock, target, loop);
                     newState.insertProxies(loopExit, loop.entryState);
                     loopExit.setStateAfter(newState.create(bci));
                 }
 
-                lastLoopExit.setNext(traget);
+                lastLoopExit.setNext(target);
                 return new Target(firstLoopExit, newState);
             }
         }
-        return new Target(traget, state);
+        return new Target(target, state);
     }
 
     private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Thu Apr 19 22:45:50 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Thu Apr 19 22:57:53 2012 +0200
@@ -31,13 +31,11 @@
 public final class LoopEndNode extends EndNode {
 
     @Input(notDataflow = true) private LoopBeginNode loopBegin;
-    @Data private boolean safepointPolling;
     @Data private int endIndex;
 
     public LoopEndNode(LoopBeginNode begin) {
         int idx = begin.nextEndIndex();
         assert idx >= 0;
-        this.safepointPolling = true;
         this.endIndex = idx;
         this.loopBegin = begin;
     }
@@ -56,15 +54,6 @@
         this.loopBegin = x;
     }
 
-
-    public void setSafepointPolling(boolean safePointPolling) {
-        this.safepointPolling = safePointPolling;
-    }
-
-    public boolean hasSafepointPolling() {
-        return safepointPolling;
-    }
-
     @Override
     public void generate(LIRGeneratorTool gen) {
         gen.visitLoopEnd(this);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Thu Apr 19 22:57:53 2012 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Marks a position in the graph where a safepoint should be emitted.
+ */
+public final class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType {
+
+    /**
+     * Will be null if this safepoint is not associated with a loop end.
+     */
+    @Data private final LoopEndNode loopEnd;
+
+    public SafepointNode(LoopEndNode loopEnd) {
+        super(StampFactory.illegal());
+        this.loopEnd = loopEnd;
+    }
+
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        gen.visitSafepointNode(this);
+    }
+
+    /**
+     * Gets the loop end (if any) associated with this safepoint.
+     */
+    public LoopEndNode loopEnd() {
+        return loopEnd;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu Apr 19 22:45:50 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu Apr 19 22:57:53 2012 +0200
@@ -97,6 +97,7 @@
     public abstract void visitMerge(MergeNode i);
     public abstract void visitEndNode(EndNode i);
     public abstract void visitLoopEnd(LoopEndNode i);
+    public abstract void visitSafepointNode(SafepointNode i);
 
     public abstract void visitCompareAndSwap(CompareAndSwapNode i);
 
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java	Thu Apr 19 22:45:50 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java	Thu Apr 19 22:57:53 2012 +0200
@@ -25,8 +25,6 @@
 import java.lang.reflect.*;
 import java.util.concurrent.*;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.util.*;
@@ -37,6 +35,8 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
 
 /**
  * Utilities for snippet installation and management.
@@ -126,10 +126,11 @@
                     new CanonicalizerPhase(target, runtime, null).apply(graph);
                 }
 
-                // TODO (gdub) remove when we have good safepoint polling elimination
-                for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
-                    end.setSafepointPolling(false);
+                // Snippets must have no safepoints
+                for (SafepointNode s : graph.getNodes(SafepointNode.class)) {
+                    graph.removeFixed(s);
                 }
+
                 new InsertStateAfterPlaceholderPhase().apply(graph);
 
                 Debug.dump(graph, "%s: Final", snippetRiMethod.name());