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 
  24 
  25 package org.graalvm.compiler.nodes;
  26 
  27 import static org.graalvm.compiler.nodeinfo.InputType.Association;
  28 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
  29 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
  30 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
  31 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
  32 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
  33 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN;
  34 
  35 import java.util.Collections;
  36 
  37 import org.graalvm.compiler.graph.Node;
  38 import org.graalvm.compiler.graph.NodeClass;
  39 import org.graalvm.compiler.nodeinfo.NodeCycles;
  40 import org.graalvm.compiler.nodeinfo.NodeInfo;
  41 import org.graalvm.compiler.nodeinfo.NodeSize;
  42 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
  43 
  44 /**
  45  * LoopEnd nodes represent a loop back-edge. When a LoopEnd is reached, execution continues at the
  46  * {@linkplain #loopBegin() loop header}.
  47  */
  48 @NodeInfo(cycles = CYCLES_1, cyclesRationale = "Backedge jmp", size = SIZE_1, sizeRationale = "Backedge jmp")
  49 public final class LoopEndNode extends AbstractEndNode {
  50 
  51     public static final NodeClass<LoopEndNode> TYPE = NodeClass.create(LoopEndNode.class);
  52 
  53     /*
  54      * The declared type of the field cannot be LoopBeginNode, because loop explosion during partial
  55      * evaluation can temporarily assign a non-loop begin. This node will then be deleted shortly
  56      * after - but we still must not have type system violations for that short amount of time.
  57      */
  58     @Input(Association) AbstractBeginNode loopBegin;
  59     protected int endIndex;
  60 
  61     /**
  62      * Most loop ends need a safepoint (flag set to true) so that garbage collection can interrupt a
  63      * long-running (possibly endless) loop. Safepoints may be disabled for two reasons: 1) Some
  64      * code must be safepoint free, i.e., uninterruptible by garbage collection. 2) An optimization
  65      * phase determined that the loop already has another safepoint or cannot be endless, so there
  66      * is no need for a loop-end safepoint.
  67      *
  68      * Note that 1) is a hard correctness issue: emitting a safepoint in uninterruptible code is a
  69      * bug, i.e., it is not allowed to set the flag back to true once it is false. To ensure that
  70      * loop ends that are created late, e.g., during control flow simplifications, have no
  71      * safepoints in such cases, the safepoints are actually disabled for the
  72      * {@link LoopBeginNode#canEndsSafepoint loop begin}. New loop ends inherit the flag value from
  73      * the loop begin.
  74      */
  75     boolean canSafepoint;
  76 
  77     public LoopEndNode(LoopBeginNode begin) {
  78         super(TYPE);
  79         int idx = begin.nextEndIndex();
  80         assert idx >= 0;
  81         this.endIndex = idx;
  82         this.loopBegin = begin;
  83         this.canSafepoint = begin.canEndsSafepoint;
  84     }
  85 
  86     @Override
  87     public AbstractMergeNode merge() {
  88         return loopBegin();
  89     }
  90 
  91     public LoopBeginNode loopBegin() {
  92         return (LoopBeginNode) loopBegin;
  93     }
  94 
  95     public void setLoopBegin(LoopBeginNode x) {
  96         updateUsages(this.loopBegin, x);
  97         this.loopBegin = x;
  98     }
  99 
 100     /**
 101      * Disables safepoints for only this loop end (in contrast to disabling it for
 102      * {@link LoopBeginNode#disableSafepoint() the whole loop}.
 103      */
 104     public void disableSafepoint() {
 105         this.canSafepoint = false;
 106     }
 107 
 108     public boolean canSafepoint() {
 109         assert !canSafepoint || loopBegin().canEndsSafepoint : "When safepoints are disabled for loop begin, safepoints must be disabled for all loop ends";
 110         return canSafepoint;
 111     }
 112 
 113     @Override
 114     public void generate(NodeLIRBuilderTool gen) {
 115         gen.visitLoopEnd(this);
 116         super.generate(gen);
 117     }
 118 
 119     @Override
 120     public boolean verify() {
 121         assertTrue(loopBegin != null, "must have a loop begin");
 122         assertTrue(hasNoUsages(), "LoopEnds can not be used");
 123         return super.verify();
 124     }
 125 
 126     /**
 127      * Returns the index of this loop end amongst its {@link LoopBeginNode}'s loop ends.<br>
 128      *
 129      * Since a LoopBeginNode also has {@linkplain LoopBeginNode#forwardEnds() forward ends}, this is
 130      * <b>not</b> the index into {@link PhiNode} values at the loop begin. Use
 131      * {@link LoopBeginNode#phiPredecessorIndex(AbstractEndNode)} for this purpose.
 132      *
 133      */
 134     int endIndex() {
 135         return endIndex;
 136     }
 137 
 138     void setEndIndex(int idx) {
 139         this.endIndex = idx;
 140     }
 141 
 142     @Override
 143     public Iterable<? extends Node> cfgSuccessors() {
 144         return Collections.emptyList();
 145     }
 146 
 147     @Override
 148     public NodeCycles estimatedNodeCycles() {
 149         if (loopBegin() == null) {
 150             return CYCLES_UNKNOWN;
 151         }
 152         if (canSafepoint()) {
 153             // jmp+read
 154             return CYCLES_2;
 155         }
 156         return super.estimatedNodeCycles();
 157     }
 158 
 159     @Override
 160     public NodeSize estimatedNodeSize() {
 161         if (loopBegin() == null) {
 162             return SIZE_UNKNOWN;
 163         }
 164         if (canSafepoint()) {
 165             return SIZE_2;
 166         }
 167         return super.estimatedNodeSize();
 168     }
 169 }