Mercurial > hg > graal-compiler
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; }