--- /dev/null 2016-05-31 09:42:47.975716356 -0700 +++ new/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java 2016-12-09 00:54:54.072628369 -0800 @@ -0,0 +1,532 @@ +/* + * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.nodes; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; + +import java.util.Map; + +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.type.AbstractObjectStamp; +import org.graalvm.compiler.core.common.type.FloatStamp; +import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.iterators.NodeIterable; +import org.graalvm.compiler.lir.ConstantValue; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.nodes.calc.FloatingNode; +import org.graalvm.compiler.nodes.spi.LIRLowerable; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; + +import jdk.vm.ci.code.CodeUtil; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.PrimitiveConstant; + +/** + * The {@code ConstantNode} represents a {@link Constant constant}. + */ +@NodeInfo(nameTemplate = "C({p#rawvalue})", cycles = CYCLES_0, size = SIZE_1) +public final class ConstantNode extends FloatingNode implements LIRLowerable { + + public static final NodeClass TYPE = NodeClass.create(ConstantNode.class); + + protected final Constant value; + + private final int stableDimension; + private final boolean isDefaultStable; + + private static ConstantNode createPrimitive(JavaConstant value) { + assert value.getJavaKind() != JavaKind.Object; + return new ConstantNode(value, StampFactory.forConstant(value)); + } + + /** + * Constructs a new node representing the specified constant. + * + * @param value the constant + */ + public ConstantNode(Constant value, Stamp stamp) { + this(value, stamp, 0, false); + } + + private ConstantNode(Constant value, Stamp stamp, int stableDimension, boolean isDefaultStable) { + super(TYPE, stamp); + assert stamp != null && stamp.isCompatible(value) : stamp + " " + value; + this.value = value; + this.stableDimension = stableDimension; + if (stableDimension == 0) { + /* + * Ensure that isDefaultStable has a canonical value to avoid having two constant nodes + * that only differ in this field. The value of isDefaultStable is only used when we + * have a stable array dimension. + */ + this.isDefaultStable = false; + } else { + this.isDefaultStable = isDefaultStable; + } + } + + /** + * @return the constant value represented by this node + */ + public Constant getValue() { + return value; + } + + /** + * @return the number of stable dimensions if this is a stable array, otherwise 0 + */ + public int getStableDimension() { + return stableDimension; + } + + /** + * @return true if this is a stable array and the default elements are considered stable + */ + public boolean isDefaultStable() { + return isDefaultStable; + } + + /** + * Gathers all the {@link ConstantNode}s that are inputs to the + * {@linkplain StructuredGraph#getNodes() live nodes} in a given graph. + */ + public static NodeIterable getConstantNodes(StructuredGraph graph) { + return graph.getNodes().filter(ConstantNode.class); + } + + /** + * Replaces this node at its usages with another node. + */ + public void replace(StructuredGraph graph, Node replacement) { + assert graph == graph(); + replaceAtUsagesAndDelete(replacement); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + LIRKind kind = gen.getLIRGeneratorTool().getLIRKind(stamp()); + if (onlyUsedInVirtualState()) { + gen.setResult(this, new ConstantValue(kind, value)); + } else { + gen.setResult(this, gen.getLIRGeneratorTool().emitConstant(kind, value)); + } + } + + private boolean onlyUsedInVirtualState() { + for (Node n : this.usages()) { + if (n instanceof VirtualState) { + // Only virtual usage. + } else { + return false; + } + } + return true; + } + + public static ConstantNode forConstant(JavaConstant constant, MetaAccessProvider metaAccess, StructuredGraph graph) { + if (constant.getJavaKind().getStackKind() == JavaKind.Int && constant.getJavaKind() != JavaKind.Int) { + return forInt(constant.asInt(), graph); + } + if (constant.getJavaKind() == JavaKind.Object) { + return unique(graph, new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess))); + } else { + return unique(graph, createPrimitive(constant)); + } + } + + public static ConstantNode forConstant(JavaConstant constant, int stableDimension, boolean isDefaultStable, MetaAccessProvider metaAccess) { + if (constant.getJavaKind().getStackKind() == JavaKind.Int && constant.getJavaKind() != JavaKind.Int) { + return forInt(constant.asInt()); + } + if (constant.getJavaKind() == JavaKind.Object) { + return new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess), stableDimension, isDefaultStable); + } else { + assert stableDimension == 0; + return createPrimitive(constant); + } + } + + public static ConstantNode forConstant(JavaConstant array, MetaAccessProvider metaAccess) { + return forConstant(array, 0, false, metaAccess); + } + + public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess, StructuredGraph graph) { + return graph.unique(new ConstantNode(constant, stamp.constant(constant, metaAccess))); + } + + public static ConstantNode forConstant(Stamp stamp, Constant constant, int stableDimension, boolean isDefaultStable, MetaAccessProvider metaAccess) { + return new ConstantNode(constant, stamp.constant(constant, metaAccess), stableDimension, isDefaultStable); + } + + public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess) { + return new ConstantNode(constant, stamp.constant(constant, metaAccess)); + } + + /** + * Returns a node for a Java primitive. + */ + public static ConstantNode forPrimitive(JavaConstant constant, StructuredGraph graph) { + assert constant.getJavaKind() != JavaKind.Object; + return forConstant(constant, null, graph); + } + + /** + * Returns a node for a Java primitive. + */ + public static ConstantNode forPrimitive(JavaConstant constant) { + assert constant.getJavaKind() != JavaKind.Object; + return forConstant(constant, null); + } + + /** + * Returns a node for a primitive of a given type. + */ + public static ConstantNode forPrimitive(Stamp stamp, JavaConstant constant, StructuredGraph graph) { + if (stamp instanceof IntegerStamp) { + assert constant.getJavaKind().isNumericInteger() && stamp.getStackKind() == constant.getJavaKind().getStackKind(); + IntegerStamp istamp = (IntegerStamp) stamp; + return forIntegerBits(istamp.getBits(), constant, graph); + } else { + assert constant.getJavaKind().isNumericFloat() && stamp.getStackKind() == constant.getJavaKind(); + return forPrimitive(constant, graph); + } + } + + /** + * Returns a node for a primitive of a given type. + */ + public static ConstantNode forPrimitive(Stamp stamp, Constant constant) { + if (stamp instanceof IntegerStamp) { + PrimitiveConstant primitive = (PrimitiveConstant) constant; + assert primitive.getJavaKind().isNumericInteger() && stamp.getStackKind() == primitive.getJavaKind().getStackKind(); + IntegerStamp istamp = (IntegerStamp) stamp; + return forIntegerBits(istamp.getBits(), primitive); + } else if (stamp instanceof FloatStamp) { + PrimitiveConstant primitive = (PrimitiveConstant) constant; + assert primitive.getJavaKind().isNumericFloat() && stamp.getStackKind() == primitive.getJavaKind(); + return forConstant(primitive, null); + } else { + assert !(stamp instanceof AbstractObjectStamp); + return new ConstantNode(constant, stamp.constant(constant, null)); + } + } + + /** + * Returns a node for a double constant. + * + * @param d the double value for which to create the instruction + * @return a node for a double constant + */ + public static ConstantNode forDouble(double d, StructuredGraph graph) { + return unique(graph, createPrimitive(JavaConstant.forDouble(d))); + } + + /** + * Returns a node for a double constant. + * + * @param d the double value for which to create the instruction + * @return a node for a double constant + */ + public static ConstantNode forDouble(double d) { + return createPrimitive(JavaConstant.forDouble(d)); + } + + /** + * Returns a node for a float constant. + * + * @param f the float value for which to create the instruction + * @return a node for a float constant + */ + public static ConstantNode forFloat(float f, StructuredGraph graph) { + return unique(graph, createPrimitive(JavaConstant.forFloat(f))); + } + + /** + * Returns a node for a float constant. + * + * @param f the float value for which to create the instruction + * @return a node for a float constant + */ + public static ConstantNode forFloat(float f) { + return createPrimitive(JavaConstant.forFloat(f)); + } + + /** + * Returns a node for an long constant. + * + * @param i the long value for which to create the instruction + * @return a node for an long constant + */ + public static ConstantNode forLong(long i, StructuredGraph graph) { + return unique(graph, createPrimitive(JavaConstant.forLong(i))); + } + + /** + * Returns a node for an long constant. + * + * @param i the long value for which to create the instruction + * @return a node for an long constant + */ + public static ConstantNode forLong(long i) { + return createPrimitive(JavaConstant.forLong(i)); + } + + /** + * Returns a node for an integer constant. + * + * @param i the integer value for which to create the instruction + * @return a node for an integer constant + */ + public static ConstantNode forInt(int i, StructuredGraph graph) { + return unique(graph, createPrimitive(JavaConstant.forInt(i))); + } + + /** + * Returns a node for an integer constant. + * + * @param i the integer value for which to create the instruction + * @return a node for an integer constant + */ + public static ConstantNode forInt(int i) { + return createPrimitive(JavaConstant.forInt(i)); + } + + /** + * Returns a node for a boolean constant. + * + * @param i the boolean value for which to create the instruction + * @return a node representing the boolean + */ + public static ConstantNode forBoolean(boolean i, StructuredGraph graph) { + return unique(graph, createPrimitive(JavaConstant.forInt(i ? 1 : 0))); + } + + /** + * Returns a node for a boolean constant. + * + * @param i the boolean value for which to create the instruction + * @return a node representing the boolean + */ + public static ConstantNode forBoolean(boolean i) { + return createPrimitive(JavaConstant.forInt(i ? 1 : 0)); + } + + /** + * Returns a node for a byte constant. + * + * @param i the byte value for which to create the instruction + * @return a node representing the byte + */ + public static ConstantNode forByte(byte i, StructuredGraph graph) { + return unique(graph, createPrimitive(JavaConstant.forInt(i))); + } + + /** + * Returns a node for a char constant. + * + * @param i the char value for which to create the instruction + * @return a node representing the char + */ + public static ConstantNode forChar(char i, StructuredGraph graph) { + return unique(graph, createPrimitive(JavaConstant.forInt(i))); + } + + /** + * Returns a node for a short constant. + * + * @param i the short value for which to create the instruction + * @return a node representing the short + */ + public static ConstantNode forShort(short i, StructuredGraph graph) { + return unique(graph, createPrimitive(JavaConstant.forInt(i))); + } + + private static ConstantNode unique(StructuredGraph graph, ConstantNode node) { + return graph.unique(node); + } + + private static ConstantNode forIntegerBits(int bits, JavaConstant constant, StructuredGraph graph) { + long value = constant.asLong(); + long bounds = CodeUtil.signExtend(value, bits); + return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds))); + } + + /** + * Returns a node for a constant integer that's not directly representable as Java primitive + * (e.g. short). + */ + public static ConstantNode forIntegerBits(int bits, long value, StructuredGraph graph) { + return forIntegerBits(bits, JavaConstant.forPrimitiveInt(bits, value), graph); + } + + private static ConstantNode forIntegerBits(int bits, JavaConstant constant) { + long value = constant.asLong(); + long bounds = CodeUtil.signExtend(value, bits); + return new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds)); + } + + /** + * Returns a node for a constant integer that's not directly representable as Java primitive + * (e.g. short). + */ + public static ConstantNode forIntegerBits(int bits, long value) { + return forIntegerBits(bits, JavaConstant.forPrimitiveInt(bits, value)); + } + + /** + * Returns a node for a constant integer that's compatible to a given stamp. + */ + public static ConstantNode forIntegerStamp(Stamp stamp, long value, StructuredGraph graph) { + if (stamp instanceof IntegerStamp) { + IntegerStamp intStamp = (IntegerStamp) stamp; + return forIntegerBits(intStamp.getBits(), value, graph); + } else { + return forIntegerKind(stamp.getStackKind(), value, graph); + } + } + + /** + * Returns a node for a constant integer that's compatible to a given stamp. + */ + public static ConstantNode forIntegerStamp(Stamp stamp, long value) { + if (stamp instanceof IntegerStamp) { + IntegerStamp intStamp = (IntegerStamp) stamp; + return forIntegerBits(intStamp.getBits(), value); + } else { + return forIntegerKind(stamp.getStackKind(), value); + } + } + + public static ConstantNode forIntegerKind(JavaKind kind, long value, StructuredGraph graph) { + switch (kind) { + case Byte: + case Short: + case Int: + return ConstantNode.forInt((int) value, graph); + case Long: + return ConstantNode.forLong(value, graph); + default: + throw GraalError.shouldNotReachHere("unknown kind " + kind); + } + } + + public static ConstantNode forIntegerKind(JavaKind kind, long value) { + switch (kind) { + case Byte: + case Short: + case Int: + return createPrimitive(JavaConstant.forInt((int) value)); + case Long: + return createPrimitive(JavaConstant.forLong(value)); + default: + throw GraalError.shouldNotReachHere("unknown kind " + kind); + } + } + + public static ConstantNode forFloatingKind(JavaKind kind, double value, StructuredGraph graph) { + switch (kind) { + case Float: + return ConstantNode.forFloat((float) value, graph); + case Double: + return ConstantNode.forDouble(value, graph); + default: + throw GraalError.shouldNotReachHere("unknown kind " + kind); + } + } + + public static ConstantNode forFloatingKind(JavaKind kind, double value) { + switch (kind) { + case Float: + return ConstantNode.forFloat((float) value); + case Double: + return ConstantNode.forDouble(value); + default: + throw GraalError.shouldNotReachHere("unknown kind " + kind); + } + } + + /** + * Returns a node for a constant double that's compatible to a given stamp. + */ + public static ConstantNode forFloatingStamp(Stamp stamp, double value, StructuredGraph graph) { + return forFloatingKind(stamp.getStackKind(), value, graph); + } + + /** + * Returns a node for a constant double that's compatible to a given stamp. + */ + public static ConstantNode forFloatingStamp(Stamp stamp, double value) { + return forFloatingKind(stamp.getStackKind(), value); + } + + public static ConstantNode defaultForKind(JavaKind kind, StructuredGraph graph) { + return unique(graph, defaultForKind(kind)); + } + + public static ConstantNode defaultForKind(JavaKind kind) { + switch (kind) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + return ConstantNode.forInt(0); + case Double: + return ConstantNode.forDouble(0.0); + case Float: + return ConstantNode.forFloat(0.0f); + case Long: + return ConstantNode.forLong(0L); + case Object: + return ConstantNode.forConstant(JavaConstant.NULL_POINTER, null); + default: + return null; + } + } + + @Override + public Map getDebugProperties(Map map) { + Map properties = super.getDebugProperties(map); + properties.put("rawvalue", value.toValueString()); + return properties; + } + + @Override + public String toString(Verbosity verbosity) { + if (verbosity == Verbosity.Name) { + return super.toString(Verbosity.Name) + "(" + value.toValueString() + ")"; + } else { + return super.toString(verbosity); + } + } +}