1 /*
   2  * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.nodes;
  24 
  25 import static org.graalvm.compiler.nodeinfo.InputType.Association;
  26 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
  27 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
  28 
  29 import java.util.Collections;
  30 
  31 import org.graalvm.compiler.graph.Node;
  32 import org.graalvm.compiler.graph.NodeClass;
  33 import org.graalvm.compiler.nodeinfo.NodeInfo;
  34 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
  35 
  36 /**
  37  * LoopEnd nodes represent a loop back-edge. When a LoopEnd is reached, execution continues at the
  38  * {@linkplain #loopBegin() loop header}.
  39  */
  40 @NodeInfo(cycles = CYCLES_1, cyclesRationale = "Backedge jmp", size = SIZE_1, sizeRationale = "Backedge jmp")
  41 public final class LoopEndNode extends AbstractEndNode {
  42 
  43     public static final NodeClass<LoopEndNode> TYPE = NodeClass.create(LoopEndNode.class);
  44 
  45     /*
  46      * The declared type of the field cannot be LoopBeginNode, because loop explosion during partial
  47      * evaluation can temporarily assign a non-loop begin. This node will then be deleted shortly
  48      * after - but we still must not have type system violations for that short amount of time.
  49      */
  50     @Input(Association) AbstractBeginNode loopBegin;
  51     protected int endIndex;
  52 
  53     /**
  54      * Most loop ends need a safepoint (flag set to true) so that garbage collection can interrupt a
  55      * long-running (possibly endless) loop. Safepoints may be disabled for two reasons: 1) Some
  56      * code must be safepoint free, i.e., uninterruptible by garbage collection. 2) An optimization
  57      * phase determined that the loop already has another safepoint or cannot be endless, so there
  58      * is no need for a loop-end safepoint.
  59      *
  60      * Note that 1) is a hard correctness issue: emitting a safepoint in uninterruptible code is a
  61      * bug, i.e., it is not allowed to set the flag back to true once it is false. To ensure that
  62      * loop ends that are created late, e.g., during control flow simplifications, have no
  63      * safepoints in such cases, the safepoints are actually disabled for the
  64      * {@link LoopBeginNode#canEndsSafepoint loop begin}. New loop ends inherit the flag value from
  65      * the loop begin.
  66      */
  67     boolean canSafepoint;
  68 
  69     public LoopEndNode(LoopBeginNode begin) {
  70         super(TYPE);
  71         int idx = begin.nextEndIndex();
  72         assert idx >= 0;
  73         this.endIndex = idx;
  74         this.loopBegin = begin;
  75         this.canSafepoint = begin.canEndsSafepoint;
  76     }
  77 
  78     @Override
  79     public AbstractMergeNode merge() {
  80         return loopBegin();
  81     }
  82 
  83     public LoopBeginNode loopBegin() {
  84         return (LoopBeginNode) loopBegin;
  85     }
  86 
  87     public void setLoopBegin(LoopBeginNode x) {
  88         updateUsages(this.loopBegin, x);
  89         this.loopBegin = x;
  90     }
  91 
  92     /**
  93      * Disables safepoints for only this loop end (in contrast to disabling it for
  94      * {@link LoopBeginNode#disableSafepoint() the whole loop}.
  95      */
  96     public void disableSafepoint() {
  97         this.canSafepoint = false;
  98     }
  99 
 100     public boolean canSafepoint() {
 101         assert !canSafepoint || loopBegin().canEndsSafepoint : "When safepoints are disabled for loop begin, safepoints must be disabled for all loop ends";
 102         return canSafepoint;
 103     }
 104 
 105     @Override
 106     public void generate(NodeLIRBuilderTool gen) {
 107         gen.visitLoopEnd(this);
 108         super.generate(gen);
 109     }
 110 
 111     @Override
 112     public boolean verify() {
 113         assertTrue(loopBegin != null, "must have a loop begin");
 114         assertTrue(hasNoUsages(), "LoopEnds can not be used");
 115         return super.verify();
 116     }
 117 
 118     /**
 119      * Returns the index of this loop end amongst its {@link LoopBeginNode}'s loop ends.<br>
 120      *
 121      * Since a LoopBeginNode also has {@linkplain LoopBeginNode#forwardEnds() forward ends}, this is
 122      * <b>not</b> the index into {@link PhiNode} values at the loop begin. Use
 123      * {@link LoopBeginNode#phiPredecessorIndex(AbstractEndNode)} for this purpose.
 124      *
 125      */
 126     int endIndex() {
 127         return endIndex;
 128     }
 129 
 130     void setEndIndex(int idx) {
 131         this.endIndex = idx;
 132     }
 133 
 134     @Override
 135     public Iterable<? extends Node> cfgSuccessors() {
 136         return Collections.emptyList();
 137     }
 138 }