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