changeset 22838:b2438b37ab3c

Document canSafepoint flag
author Christian Wimmer <christian.wimmer@oracle.com>
date Thu, 15 Oct 2015 11:29:00 -0700
parents 77ef4d74a6b2
children e5879d8381dd
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java
diffstat 2 files changed, 23 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Thu Oct 15 16:32:43 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Thu Oct 15 11:29:00 2015 -0700
@@ -49,20 +49,22 @@
     protected int nextEndIndex;
     protected int unswitches;
     protected int inversionCount;
-    boolean canSafepoint;
+
+    /** See {@link LoopEndNode#canSafepoint} for more information. */
+    boolean canEndsSafepoint;
 
     @OptionalInput(InputType.Guard) GuardingNode overflowGuard;
 
     public LoopBeginNode() {
         super(TYPE);
         loopFrequency = 1;
-        this.canSafepoint = true;
+        this.canEndsSafepoint = true;
     }
 
     /** Disables safepoint for the whole loop, i.e., for all {@link LoopEndNode loop ends}. */
     public void disableSafepoint() {
         /* Store flag locally in case new loop ends are created later on. */
-        this.canSafepoint = false;
+        this.canEndsSafepoint = false;
         /* Propagate flag to all existing loop ends. */
         for (LoopEndNode loopEnd : loopEnds()) {
             loopEnd.disableSafepoint();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Thu Oct 15 16:32:43 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Thu Oct 15 11:29:00 2015 -0700
@@ -39,16 +39,31 @@
 
     public static final NodeClass<LoopEndNode> TYPE = NodeClass.create(LoopEndNode.class);
     @Input(InputType.Association) LoopBeginNode loopBegin;
-    private boolean canSafepoint;
     protected int endIndex;
 
+    /**
+     * Most loop ends need a safepoint (flag set to true) so that garbage collection can interrupt a
+     * long-running (possibly endless) loop. Safepoints may be disabled for two reasons: 1) Some
+     * code must be safepoint free, i.e., uninterruptible by garbage collection. 2) An optimization
+     * phase determined that the loop already has another safepoint or cannot be endless, so there
+     * is no need for a loop-end safepoint.
+     *
+     * Note that 1) is a hard correctness issue: emitting a safepoint in uninterruptible code is a
+     * bug, i.e., it is not allowed to set the flag back to true once it is false. To ensure that
+     * loop ends that are created late, e.g., during control flow simplifications, have no
+     * safepoints in such cases, the safepoints are actually disabled for the
+     * {@link LoopBeginNode#canEndsSafepoint loop begin}. New loop ends inherit the flag value from
+     * the loop begin.
+     */
+    boolean canSafepoint;
+
     public LoopEndNode(LoopBeginNode begin) {
         super(TYPE);
         int idx = begin.nextEndIndex();
         assert idx >= 0;
         this.endIndex = idx;
         this.loopBegin = begin;
-        this.canSafepoint = begin.canSafepoint;
+        this.canSafepoint = begin.canEndsSafepoint;
     }
 
     @Override
@@ -74,7 +89,7 @@
     }
 
     public boolean canSafepoint() {
-        assert !canSafepoint || loopBegin.canSafepoint : "When safepoints are disabled for loop begin, safepoints must be disabled for all loop ends";
+        assert !canSafepoint || loopBegin.canEndsSafepoint : "When safepoints are disabled for loop begin, safepoints must be disabled for all loop ends";
         return canSafepoint;
     }