1 /* 2 * Copyright (c) 2009, 2016, 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 java.util.function.Predicate; 26 27 import org.graalvm.compiler.core.common.type.Stamp; 28 import org.graalvm.compiler.graph.Node; 29 import org.graalvm.compiler.graph.NodeClass; 30 import org.graalvm.compiler.graph.iterators.NodePredicate; 31 import org.graalvm.compiler.nodeinfo.InputType; 32 import org.graalvm.compiler.nodeinfo.NodeInfo; 33 import org.graalvm.compiler.nodeinfo.Verbosity; 34 import org.graalvm.compiler.nodes.spi.NodeValueMap; 35 36 import jdk.vm.ci.meta.Constant; 37 import jdk.vm.ci.meta.JavaConstant; 38 import jdk.vm.ci.meta.JavaKind; 39 40 /** 41 * This class represents a value within the graph, including local variables, phis, and all other 42 * instructions. 43 */ 44 @NodeInfo 45 public abstract class ValueNode extends org.graalvm.compiler.graph.Node implements ValueNodeInterface { 46 47 public static final NodeClass<ValueNode> TYPE = NodeClass.create(ValueNode.class); 48 /** 49 * The kind of this value. This is {@link JavaKind#Void} for instructions that produce no value. 50 * This kind is guaranteed to be a {@linkplain JavaKind#getStackKind() stack kind}. 51 */ 52 protected Stamp stamp; 53 54 public ValueNode(NodeClass<? extends ValueNode> c, Stamp stamp) { 55 super(c); 56 this.stamp = stamp; 57 } 58 59 public final Stamp stamp() { 60 return stamp; 61 } 62 63 public final void setStamp(Stamp stamp) { 64 this.stamp = stamp; 65 assert !isAlive() || !inferStamp() : "setStamp called on a node that overrides inferStamp: " + this; 66 } 67 68 @Override 69 public final StructuredGraph graph() { 70 return (StructuredGraph) super.graph(); 71 } 72 73 /** 74 * Checks if the given stamp is different than the current one ( 75 * {@code newStamp.equals(oldStamp) == false}). If it is different then the new stamp will 76 * become the current stamp for this node. 77 * 78 * @return true if the stamp has changed, false otherwise. 79 */ 80 protected final boolean updateStamp(Stamp newStamp) { 81 if (newStamp == null || newStamp.equals(stamp)) { 82 return false; 83 } else { 84 stamp = newStamp; 85 return true; 86 } 87 } 88 89 /** 90 * This method can be overridden by subclasses of {@link ValueNode} if they need to recompute 91 * their stamp if their inputs change. A typical implementation will compute the stamp and pass 92 * it to {@link #updateStamp(Stamp)}, whose return value can be used as the result of this 93 * method. 94 * 95 * @return true if the stamp has changed, false otherwise. 96 */ 97 public boolean inferStamp() { 98 return false; 99 } 100 101 public final JavaKind getStackKind() { 102 return stamp().getStackKind(); 103 } 104 105 /** 106 * Checks whether this value is a constant (i.e. it is of type {@link ConstantNode}. 107 * 108 * @return {@code true} if this value is a constant 109 */ 110 public final boolean isConstant() { 111 return this instanceof ConstantNode; 112 } 113 114 private static final NodePredicate IS_CONSTANT = new NodePredicate() { 115 @Override 116 public boolean apply(Node n) { 117 return n instanceof ConstantNode; 118 } 119 }; 120 121 public static NodePredicate isConstantPredicate() { 122 return IS_CONSTANT; 123 } 124 125 /** 126 * Checks whether this value represents the null constant. 127 * 128 * @return {@code true} if this value represents the null constant 129 */ 130 public final boolean isNullConstant() { 131 JavaConstant value = asJavaConstant(); 132 return value != null && value.isNull(); 133 } 134 135 /** 136 * Convert this value to a constant if it is a constant, otherwise return null. 137 * 138 * @return the {@link JavaConstant} represented by this value if it is a constant; {@code null} 139 * otherwise 140 */ 141 public final Constant asConstant() { 142 if (this instanceof ConstantNode) { 143 return ((ConstantNode) this).getValue(); 144 } else { 145 return null; 146 } 147 } 148 149 public final boolean isJavaConstant() { 150 return isConstant() && asConstant() instanceof JavaConstant; 151 } 152 153 public final JavaConstant asJavaConstant() { 154 Constant value = asConstant(); 155 if (value instanceof JavaConstant) { 156 return (JavaConstant) value; 157 } else { 158 return null; 159 } 160 } 161 162 @Override 163 public ValueNode asNode() { 164 return this; 165 } 166 167 @Override 168 public boolean isAllowedUsageType(InputType type) { 169 if (getStackKind() != JavaKind.Void && type == InputType.Value) { 170 return true; 171 } else { 172 return super.isAllowedUsageType(type); 173 } 174 } 175 176 /** 177 * Checks if this node has usages other than the given node {@code node}. 178 * 179 * @param node node which is ignored when searching for usages 180 * @param nodeValueMap 181 * @return true if this node has other usages, false otherwise 182 */ 183 public boolean hasUsagesOtherThan(ValueNode node, NodeValueMap nodeValueMap) { 184 for (Node usage : usages()) { 185 if (usage != node && usage instanceof ValueNode && nodeValueMap.hasOperand(usage)) { 186 return true; 187 } 188 } 189 return false; 190 } 191 192 @Override 193 protected void replaceAtUsages(Node other, Predicate<Node> filter, Node toBeDeleted) { 194 super.replaceAtUsages(other, filter, toBeDeleted); 195 assert checkReplaceAtUsagesInvariants(other); 196 } 197 198 private boolean checkReplaceAtUsagesInvariants(Node other) { 199 assert other == null || other instanceof ValueNode; 200 if (this.hasUsages() && !this.stamp().isEmpty() && !(other instanceof PhiNode) && other != null) { 201 assert ((ValueNode) other).stamp().getClass() == stamp().getClass() : "stamp have to be of same class"; 202 boolean morePrecise = ((ValueNode) other).stamp().join(stamp()).equals(((ValueNode) other).stamp()); 203 assert morePrecise : "stamp can only get more precise " + toString(Verbosity.All) + " " + 204 other.toString(Verbosity.All); 205 } 206 return true; 207 } 208 }