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 static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; 26 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; 27 28 import java.util.Map; 29 30 import org.graalvm.compiler.core.common.LIRKind; 31 import org.graalvm.compiler.core.common.type.AbstractObjectStamp; 32 import org.graalvm.compiler.core.common.type.FloatStamp; 33 import org.graalvm.compiler.core.common.type.IntegerStamp; 34 import org.graalvm.compiler.core.common.type.Stamp; 35 import org.graalvm.compiler.core.common.type.StampFactory; 36 import org.graalvm.compiler.debug.GraalError; 37 import org.graalvm.compiler.graph.Node; 38 import org.graalvm.compiler.graph.NodeClass; 39 import org.graalvm.compiler.graph.iterators.NodeIterable; 40 import org.graalvm.compiler.lir.ConstantValue; 41 import org.graalvm.compiler.nodeinfo.NodeInfo; 42 import org.graalvm.compiler.nodeinfo.Verbosity; 43 import org.graalvm.compiler.nodes.calc.FloatingNode; 44 import org.graalvm.compiler.nodes.spi.LIRLowerable; 45 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 46 47 import jdk.vm.ci.code.CodeUtil; 48 import jdk.vm.ci.meta.Constant; 49 import jdk.vm.ci.meta.JavaConstant; 50 import jdk.vm.ci.meta.JavaKind; 51 import jdk.vm.ci.meta.MetaAccessProvider; 52 import jdk.vm.ci.meta.PrimitiveConstant; 53 54 /** 55 * The {@code ConstantNode} represents a {@link Constant constant}. 56 */ 57 @NodeInfo(nameTemplate = "C({p#rawvalue}) {p#stampKind}", cycles = CYCLES_0, size = SIZE_1) 58 public final class ConstantNode extends FloatingNode implements LIRLowerable { 59 60 public static final NodeClass<ConstantNode> TYPE = NodeClass.create(ConstantNode.class); 61 62 protected final Constant value; 63 64 private final int stableDimension; 65 private final boolean isDefaultStable; 66 67 private static ConstantNode createPrimitive(JavaConstant value) { 68 assert value.getJavaKind() != JavaKind.Object; 69 return new ConstantNode(value, StampFactory.forConstant(value)); 70 } 71 72 /** 73 * Constructs a new node representing the specified constant. 74 * 75 * @param value the constant 76 */ 77 public ConstantNode(Constant value, Stamp stamp) { 78 this(value, stamp, 0, false); 79 } 80 81 private ConstantNode(Constant value, Stamp stamp, int stableDimension, boolean isDefaultStable) { 82 super(TYPE, stamp); 83 assert stamp != null && stamp.isCompatible(value) : stamp + " " + value; 84 this.value = value; 85 this.stableDimension = stableDimension; 86 if (stableDimension == 0) { 87 /* 88 * Ensure that isDefaultStable has a canonical value to avoid having two constant nodes 89 * that only differ in this field. The value of isDefaultStable is only used when we 90 * have a stable array dimension. 91 */ 92 this.isDefaultStable = false; 93 } else { 94 this.isDefaultStable = isDefaultStable; 95 } 96 } 97 98 /** 99 * @return the constant value represented by this node 100 */ 101 public Constant getValue() { 102 return value; 103 } 104 105 /** 106 * @return the number of stable dimensions if this is a stable array, otherwise 0 107 */ 108 public int getStableDimension() { 109 return stableDimension; 110 } 111 112 /** 113 * @return true if this is a stable array and the default elements are considered stable 114 */ 115 public boolean isDefaultStable() { 116 return isDefaultStable; 117 } 118 119 /** 120 * Gathers all the {@link ConstantNode}s that are inputs to the 121 * {@linkplain StructuredGraph#getNodes() live nodes} in a given graph. 122 */ 123 public static NodeIterable<ConstantNode> getConstantNodes(StructuredGraph graph) { 124 return graph.getNodes().filter(ConstantNode.class); 125 } 126 127 /** 128 * Replaces this node at its usages with another node. 129 */ 130 public void replace(StructuredGraph graph, Node replacement) { 131 assert graph == graph(); 132 replaceAtUsagesAndDelete(replacement); 133 } 134 135 @Override 136 public void generate(NodeLIRBuilderTool gen) { 137 LIRKind kind = gen.getLIRGeneratorTool().getLIRKind(stamp()); 138 if (onlyUsedInVirtualState()) { 139 gen.setResult(this, new ConstantValue(kind, value)); 140 } else { 141 gen.setResult(this, gen.getLIRGeneratorTool().emitConstant(kind, value)); 142 } 143 } 144 145 private boolean onlyUsedInVirtualState() { 146 for (Node n : this.usages()) { 147 if (n instanceof VirtualState) { 148 // Only virtual usage. 149 } else { 150 return false; 151 } 152 } 153 return true; 154 } 155 156 public static ConstantNode forConstant(JavaConstant constant, MetaAccessProvider metaAccess, StructuredGraph graph) { 157 if (constant.getJavaKind().getStackKind() == JavaKind.Int && constant.getJavaKind() != JavaKind.Int) { 158 return forInt(constant.asInt(), graph); 159 } 160 if (constant.getJavaKind() == JavaKind.Object) { 161 return unique(graph, new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess))); 162 } else { 163 return unique(graph, createPrimitive(constant)); 164 } 165 } 166 167 public static ConstantNode forConstant(JavaConstant constant, int stableDimension, boolean isDefaultStable, MetaAccessProvider metaAccess) { 168 if (constant.getJavaKind().getStackKind() == JavaKind.Int && constant.getJavaKind() != JavaKind.Int) { 169 return forInt(constant.asInt()); 170 } 171 if (constant.getJavaKind() == JavaKind.Object) { 172 return new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess), stableDimension, isDefaultStable); 173 } else { 174 assert stableDimension == 0; 175 return createPrimitive(constant); 176 } 177 } 178 179 public static ConstantNode forConstant(JavaConstant array, MetaAccessProvider metaAccess) { 180 return forConstant(array, 0, false, metaAccess); 181 } 182 183 public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess, StructuredGraph graph) { 184 return graph.unique(new ConstantNode(constant, stamp.constant(constant, metaAccess))); 185 } 186 187 public static ConstantNode forConstant(Stamp stamp, Constant constant, int stableDimension, boolean isDefaultStable, MetaAccessProvider metaAccess) { 188 return new ConstantNode(constant, stamp.constant(constant, metaAccess), stableDimension, isDefaultStable); 189 } 190 191 public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess) { 192 return new ConstantNode(constant, stamp.constant(constant, metaAccess)); 193 } 194 195 /** 196 * Returns a node for a Java primitive. 197 */ 198 public static ConstantNode forPrimitive(JavaConstant constant, StructuredGraph graph) { 199 assert constant.getJavaKind() != JavaKind.Object; 200 return forConstant(constant, null, graph); 201 } 202 203 /** 204 * Returns a node for a Java primitive. 205 */ 206 public static ConstantNode forPrimitive(JavaConstant constant) { 207 assert constant.getJavaKind() != JavaKind.Object; 208 return forConstant(constant, null); 209 } 210 211 /** 212 * Returns a node for a primitive of a given type. 213 */ 214 public static ConstantNode forPrimitive(Stamp stamp, JavaConstant constant, StructuredGraph graph) { 215 if (stamp instanceof IntegerStamp) { 216 assert constant.getJavaKind().isNumericInteger() && stamp.getStackKind() == constant.getJavaKind().getStackKind(); 217 IntegerStamp istamp = (IntegerStamp) stamp; 218 return forIntegerBits(istamp.getBits(), constant, graph); 219 } else { 220 assert constant.getJavaKind().isNumericFloat() && stamp.getStackKind() == constant.getJavaKind(); 221 return forPrimitive(constant, graph); 222 } 223 } 224 225 /** 226 * Returns a node for a primitive of a given type. 227 */ 228 public static ConstantNode forPrimitive(Stamp stamp, Constant constant) { 229 if (stamp instanceof IntegerStamp) { 230 PrimitiveConstant primitive = (PrimitiveConstant) constant; 231 assert primitive.getJavaKind().isNumericInteger() && stamp.getStackKind() == primitive.getJavaKind().getStackKind(); 232 IntegerStamp istamp = (IntegerStamp) stamp; 233 return forIntegerBits(istamp.getBits(), primitive); 234 } else if (stamp instanceof FloatStamp) { 235 PrimitiveConstant primitive = (PrimitiveConstant) constant; 236 assert primitive.getJavaKind().isNumericFloat() && stamp.getStackKind() == primitive.getJavaKind(); 237 return forConstant(primitive, null); 238 } else { 239 assert !(stamp instanceof AbstractObjectStamp); 240 return new ConstantNode(constant, stamp.constant(constant, null)); 241 } 242 } 243 244 /** 245 * Returns a node for a double constant. 246 * 247 * @param d the double value for which to create the instruction 248 * @return a node for a double constant 249 */ 250 public static ConstantNode forDouble(double d, StructuredGraph graph) { 251 return unique(graph, createPrimitive(JavaConstant.forDouble(d))); 252 } 253 254 /** 255 * Returns a node for a double constant. 256 * 257 * @param d the double value for which to create the instruction 258 * @return a node for a double constant 259 */ 260 public static ConstantNode forDouble(double d) { 261 return createPrimitive(JavaConstant.forDouble(d)); 262 } 263 264 /** 265 * Returns a node for a float constant. 266 * 267 * @param f the float value for which to create the instruction 268 * @return a node for a float constant 269 */ 270 public static ConstantNode forFloat(float f, StructuredGraph graph) { 271 return unique(graph, createPrimitive(JavaConstant.forFloat(f))); 272 } 273 274 /** 275 * Returns a node for a float constant. 276 * 277 * @param f the float value for which to create the instruction 278 * @return a node for a float constant 279 */ 280 public static ConstantNode forFloat(float f) { 281 return createPrimitive(JavaConstant.forFloat(f)); 282 } 283 284 /** 285 * Returns a node for an long constant. 286 * 287 * @param i the long value for which to create the instruction 288 * @return a node for an long constant 289 */ 290 public static ConstantNode forLong(long i, StructuredGraph graph) { 291 return unique(graph, createPrimitive(JavaConstant.forLong(i))); 292 } 293 294 /** 295 * Returns a node for an long constant. 296 * 297 * @param i the long value for which to create the instruction 298 * @return a node for an long constant 299 */ 300 public static ConstantNode forLong(long i) { 301 return createPrimitive(JavaConstant.forLong(i)); 302 } 303 304 /** 305 * Returns a node for an integer constant. 306 * 307 * @param i the integer value for which to create the instruction 308 * @return a node for an integer constant 309 */ 310 public static ConstantNode forInt(int i, StructuredGraph graph) { 311 return unique(graph, createPrimitive(JavaConstant.forInt(i))); 312 } 313 314 /** 315 * Returns a node for an integer constant. 316 * 317 * @param i the integer value for which to create the instruction 318 * @return a node for an integer constant 319 */ 320 public static ConstantNode forInt(int i) { 321 return createPrimitive(JavaConstant.forInt(i)); 322 } 323 324 /** 325 * Returns a node for a boolean constant. 326 * 327 * @param i the boolean value for which to create the instruction 328 * @return a node representing the boolean 329 */ 330 public static ConstantNode forBoolean(boolean i, StructuredGraph graph) { 331 return unique(graph, createPrimitive(JavaConstant.forInt(i ? 1 : 0))); 332 } 333 334 /** 335 * Returns a node for a boolean constant. 336 * 337 * @param i the boolean value for which to create the instruction 338 * @return a node representing the boolean 339 */ 340 public static ConstantNode forBoolean(boolean i) { 341 return createPrimitive(JavaConstant.forInt(i ? 1 : 0)); 342 } 343 344 /** 345 * Returns a node for a byte constant. 346 * 347 * @param i the byte value for which to create the instruction 348 * @return a node representing the byte 349 */ 350 public static ConstantNode forByte(byte i, StructuredGraph graph) { 351 return unique(graph, createPrimitive(JavaConstant.forInt(i))); 352 } 353 354 /** 355 * Returns a node for a char constant. 356 * 357 * @param i the char value for which to create the instruction 358 * @return a node representing the char 359 */ 360 public static ConstantNode forChar(char i, StructuredGraph graph) { 361 return unique(graph, createPrimitive(JavaConstant.forInt(i))); 362 } 363 364 /** 365 * Returns a node for a short constant. 366 * 367 * @param i the short value for which to create the instruction 368 * @return a node representing the short 369 */ 370 public static ConstantNode forShort(short i, StructuredGraph graph) { 371 return unique(graph, createPrimitive(JavaConstant.forInt(i))); 372 } 373 374 private static ConstantNode unique(StructuredGraph graph, ConstantNode node) { 375 return graph.unique(node); 376 } 377 378 private static ConstantNode forIntegerBits(int bits, JavaConstant constant, StructuredGraph graph) { 379 long value = constant.asLong(); 380 long bounds = CodeUtil.signExtend(value, bits); 381 return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds))); 382 } 383 384 /** 385 * Returns a node for a constant integer that's not directly representable as Java primitive 386 * (e.g. short). 387 */ 388 public static ConstantNode forIntegerBits(int bits, long value, StructuredGraph graph) { 389 return forIntegerBits(bits, JavaConstant.forPrimitiveInt(bits, value), graph); 390 } 391 392 private static ConstantNode forIntegerBits(int bits, JavaConstant constant) { 393 long value = constant.asLong(); 394 long bounds = CodeUtil.signExtend(value, bits); 395 return new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds)); 396 } 397 398 /** 399 * Returns a node for a constant integer that's not directly representable as Java primitive 400 * (e.g. short). 401 */ 402 public static ConstantNode forIntegerBits(int bits, long value) { 403 return forIntegerBits(bits, JavaConstant.forPrimitiveInt(bits, value)); 404 } 405 406 /** 407 * Returns a node for a constant integer that's compatible to a given stamp. 408 */ 409 public static ConstantNode forIntegerStamp(Stamp stamp, long value, StructuredGraph graph) { 410 if (stamp instanceof IntegerStamp) { 411 IntegerStamp intStamp = (IntegerStamp) stamp; 412 return forIntegerBits(intStamp.getBits(), value, graph); 413 } else { 414 return forIntegerKind(stamp.getStackKind(), value, graph); 415 } 416 } 417 418 /** 419 * Returns a node for a constant integer that's compatible to a given stamp. 420 */ 421 public static ConstantNode forIntegerStamp(Stamp stamp, long value) { 422 if (stamp instanceof IntegerStamp) { 423 IntegerStamp intStamp = (IntegerStamp) stamp; 424 return forIntegerBits(intStamp.getBits(), value); 425 } else { 426 return forIntegerKind(stamp.getStackKind(), value); 427 } 428 } 429 430 public static ConstantNode forIntegerKind(JavaKind kind, long value, StructuredGraph graph) { 431 switch (kind) { 432 case Byte: 433 case Short: 434 case Int: 435 return ConstantNode.forInt((int) value, graph); 436 case Long: 437 return ConstantNode.forLong(value, graph); 438 default: 439 throw GraalError.shouldNotReachHere("unknown kind " + kind); 440 } 441 } 442 443 public static ConstantNode forIntegerKind(JavaKind kind, long value) { 444 switch (kind) { 445 case Byte: 446 case Short: 447 case Int: 448 return createPrimitive(JavaConstant.forInt((int) value)); 449 case Long: 450 return createPrimitive(JavaConstant.forLong(value)); 451 default: 452 throw GraalError.shouldNotReachHere("unknown kind " + kind); 453 } 454 } 455 456 public static ConstantNode forFloatingKind(JavaKind kind, double value, StructuredGraph graph) { 457 switch (kind) { 458 case Float: 459 return ConstantNode.forFloat((float) value, graph); 460 case Double: 461 return ConstantNode.forDouble(value, graph); 462 default: 463 throw GraalError.shouldNotReachHere("unknown kind " + kind); 464 } 465 } 466 467 public static ConstantNode forFloatingKind(JavaKind kind, double value) { 468 switch (kind) { 469 case Float: 470 return ConstantNode.forFloat((float) value); 471 case Double: 472 return ConstantNode.forDouble(value); 473 default: 474 throw GraalError.shouldNotReachHere("unknown kind " + kind); 475 } 476 } 477 478 /** 479 * Returns a node for a constant double that's compatible to a given stamp. 480 */ 481 public static ConstantNode forFloatingStamp(Stamp stamp, double value, StructuredGraph graph) { 482 return forFloatingKind(stamp.getStackKind(), value, graph); 483 } 484 485 /** 486 * Returns a node for a constant double that's compatible to a given stamp. 487 */ 488 public static ConstantNode forFloatingStamp(Stamp stamp, double value) { 489 return forFloatingKind(stamp.getStackKind(), value); 490 } 491 492 public static ConstantNode defaultForKind(JavaKind kind, StructuredGraph graph) { 493 return unique(graph, defaultForKind(kind)); 494 } 495 496 public static ConstantNode defaultForKind(JavaKind kind) { 497 switch (kind) { 498 case Boolean: 499 case Byte: 500 case Char: 501 case Short: 502 case Int: 503 return ConstantNode.forInt(0); 504 case Double: 505 return ConstantNode.forDouble(0.0); 506 case Float: 507 return ConstantNode.forFloat(0.0f); 508 case Long: 509 return ConstantNode.forLong(0L); 510 case Object: 511 return ConstantNode.forConstant(JavaConstant.NULL_POINTER, null); 512 default: 513 return null; 514 } 515 } 516 517 @Override 518 public Map<Object, Object> getDebugProperties(Map<Object, Object> map) { 519 Map<Object, Object> properties = super.getDebugProperties(map); 520 properties.put("rawvalue", value.toValueString()); 521 properties.put("stampKind", stamp.unrestricted().toString()); 522 return properties; 523 } 524 525 @Override 526 public String toString(Verbosity verbosity) { 527 if (verbosity == Verbosity.Name) { 528 return super.toString(Verbosity.Name) + "(" + value.toValueString() + ", " + stamp().unrestricted().toString() + ")"; 529 } else { 530 return super.toString(verbosity); 531 } 532 } 533 }