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