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