1 /*
   2  * Copyright (c) 2011, 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 java.util.Iterator;
  28 import java.util.NoSuchElementException;
  29 
  30 import org.graalvm.compiler.core.common.type.Stamp;
  31 import org.graalvm.compiler.core.common.type.StampFactory;
  32 import org.graalvm.compiler.graph.IterableNodeType;
  33 import org.graalvm.compiler.graph.Node;
  34 import org.graalvm.compiler.graph.NodeClass;
  35 import org.graalvm.compiler.graph.iterators.NodeIterable;
  36 import org.graalvm.compiler.nodeinfo.InputType;
  37 import org.graalvm.compiler.nodeinfo.NodeInfo;
  38 import org.graalvm.compiler.nodes.extended.AnchoringNode;
  39 import org.graalvm.compiler.nodes.extended.GuardingNode;
  40 import org.graalvm.compiler.nodes.spi.LIRLowerable;
  41 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
  42 
  43 @NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor})
  44 public abstract class AbstractBeginNode extends FixedWithNextNode implements LIRLowerable, GuardingNode, AnchoringNode, IterableNodeType {
  45 
  46     public static final NodeClass<AbstractBeginNode> TYPE = NodeClass.create(AbstractBeginNode.class);
  47 
  48     protected AbstractBeginNode(NodeClass<? extends AbstractBeginNode> c) {
  49         this(c, StampFactory.forVoid());
  50     }
  51 
  52     protected AbstractBeginNode(NodeClass<? extends AbstractBeginNode> c, Stamp stamp) {
  53         super(c, stamp);
  54     }
  55 
  56     public static AbstractBeginNode prevBegin(FixedNode from) {
  57         Node next = from;
  58         while (next != null) {
  59             if (next instanceof AbstractBeginNode) {
  60                 AbstractBeginNode begin = (AbstractBeginNode) next;
  61                 return begin;
  62             }
  63             next = next.predecessor();
  64         }
  65         return null;
  66     }
  67 
  68     private void evacuateGuards(FixedNode evacuateFrom) {
  69         if (!hasNoUsages()) {
  70             AbstractBeginNode prevBegin = prevBegin(evacuateFrom);
  71             assert prevBegin != null;
  72             for (Node anchored : anchored().snapshot()) {
  73                 anchored.replaceFirstInput(this, prevBegin);
  74             }
  75         }
  76     }
  77 
  78     public void prepareDelete() {
  79         prepareDelete((FixedNode) predecessor());
  80     }
  81 
  82     public void prepareDelete(FixedNode evacuateFrom) {
  83         evacuateGuards(evacuateFrom);
  84     }
  85 
  86     @Override
  87     public boolean verify() {
  88         assertTrue(predecessor() != null || this == graph().start() || this instanceof AbstractMergeNode, "begin nodes must be connected");
  89         return super.verify();
  90     }
  91 
  92     @Override
  93     public void generate(NodeLIRBuilderTool gen) {
  94         // nop
  95     }
  96 
  97     public NodeIterable<GuardNode> guards() {
  98         return usages().filter(GuardNode.class);
  99     }
 100 
 101     public NodeIterable<Node> anchored() {
 102         return usages();
 103     }
 104 
 105     public NodeIterable<FixedNode> getBlockNodes() {
 106         return new NodeIterable<FixedNode>() {
 107 
 108             @Override
 109             public Iterator<FixedNode> iterator() {
 110                 return new BlockNodeIterator(AbstractBeginNode.this);
 111             }
 112         };
 113     }
 114 
 115     private static class BlockNodeIterator implements Iterator<FixedNode> {
 116 
 117         private FixedNode current;
 118 
 119         BlockNodeIterator(FixedNode next) {
 120             this.current = next;
 121         }
 122 
 123         @Override
 124         public boolean hasNext() {
 125             return current != null;
 126         }
 127 
 128         @Override
 129         public FixedNode next() {
 130             FixedNode ret = current;
 131             if (ret == null) {
 132                 throw new NoSuchElementException();
 133             }
 134             if (current instanceof FixedWithNextNode) {
 135                 current = ((FixedWithNextNode) current).next();
 136                 if (current instanceof AbstractBeginNode) {
 137                     current = null;
 138                 }
 139             } else {
 140                 current = null;
 141             }
 142             return ret;
 143         }
 144 
 145         @Override
 146         public void remove() {
 147             throw new UnsupportedOperationException();
 148         }
 149     }
 150 }