| /* |
| * Copyright (c) 2009, 2015, 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 jdk.vm.ci.meta; |
| |
| /** |
| * Represents a constant (boxed) value, such as an integer, floating point number, or object |
| * reference, within the compiler and across the compiler/runtime interface. Exports a set of |
| * {@code JavaConstant} instances that represent frequently used constant values, such as |
| * {@link #NULL_POINTER}. |
| */ |
| public interface JavaConstant extends Constant, JavaValue { |
| /* |
| * Using a larger cache for integers leads to only a slight increase in cache hit ratio which is |
| * not enough to justify the impact on startup time. |
| */ |
| JavaConstant NULL_POINTER = new NullConstant(); |
| PrimitiveConstant INT_MINUS_1 = new PrimitiveConstant(JavaKind.Int, -1); |
| PrimitiveConstant INT_0 = new PrimitiveConstant(JavaKind.Int, 0); |
| PrimitiveConstant INT_1 = new PrimitiveConstant(JavaKind.Int, 1); |
| PrimitiveConstant INT_2 = new PrimitiveConstant(JavaKind.Int, 2); |
| PrimitiveConstant LONG_0 = new PrimitiveConstant(JavaKind.Long, 0L); |
| PrimitiveConstant LONG_1 = new PrimitiveConstant(JavaKind.Long, 1L); |
| PrimitiveConstant FLOAT_0 = new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(0.0F)); |
| PrimitiveConstant FLOAT_1 = new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(1.0F)); |
| PrimitiveConstant DOUBLE_0 = new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(0.0D)); |
| PrimitiveConstant DOUBLE_1 = new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(1.0D)); |
| PrimitiveConstant TRUE = new PrimitiveConstant(JavaKind.Boolean, 1L); |
| PrimitiveConstant FALSE = new PrimitiveConstant(JavaKind.Boolean, 0L); |
| |
| /** |
| * Returns the Java kind of this constant. |
| */ |
| JavaKind getJavaKind(); |
| |
| /** |
| * Checks whether this constant is null. |
| * |
| * @return {@code true} if this constant is the null constant |
| */ |
| boolean isNull(); |
| |
| static boolean isNull(Constant c) { |
| if (c instanceof JavaConstant) { |
| return ((JavaConstant) c).isNull(); |
| } else { |
| return false; |
| } |
| } |
| |
| /** |
| * Checks whether this constant is non-null. |
| * |
| * @return {@code true} if this constant is a primitive, or an object constant that is not null |
| */ |
| default boolean isNonNull() { |
| return !isNull(); |
| } |
| |
| /** |
| * Checks whether this constant is the default value for its kind (null, 0, 0.0, false). |
| * |
| * @return {@code true} if this constant is the default value for its kind |
| */ |
| boolean isDefaultForKind(); |
| |
| /** |
| * Returns the value of this constant as a boxed Java value. |
| * |
| * @return the value of this constant |
| */ |
| Object asBoxedPrimitive(); |
| |
| /** |
| * Returns the primitive int value this constant represents. The constant must have a |
| * {@link JavaKind#getStackKind()} of {@link JavaKind#Int}. |
| * |
| * @return the constant value |
| */ |
| int asInt(); |
| |
| /** |
| * Returns the primitive boolean value this constant represents. The constant must have kind |
| * {@link JavaKind#Boolean}. |
| * |
| * @return the constant value |
| */ |
| boolean asBoolean(); |
| |
| /** |
| * Returns the primitive long value this constant represents. The constant must have kind |
| * {@link JavaKind#Long}, a {@link JavaKind#getStackKind()} of {@link JavaKind#Int}. |
| * |
| * @return the constant value |
| */ |
| long asLong(); |
| |
| /** |
| * Returns the primitive float value this constant represents. The constant must have kind |
| * {@link JavaKind#Float}. |
| * |
| * @return the constant value |
| */ |
| float asFloat(); |
| |
| /** |
| * Returns the primitive double value this constant represents. The constant must have kind |
| * {@link JavaKind#Double}. |
| * |
| * @return the constant value |
| */ |
| double asDouble(); |
| |
| default String toValueString() { |
| if (getJavaKind() == JavaKind.Illegal) { |
| return "illegal"; |
| } else { |
| return getJavaKind().format(asBoxedPrimitive()); |
| } |
| } |
| |
| static String toString(JavaConstant constant) { |
| if (constant.getJavaKind() == JavaKind.Illegal) { |
| return "illegal"; |
| } else { |
| return constant.getJavaKind().getJavaName() + "[" + constant.toValueString() + "]"; |
| } |
| } |
| |
| /** |
| * Creates a boxed double constant. |
| * |
| * @param d the double value to box |
| * @return a boxed copy of {@code value} |
| */ |
| static PrimitiveConstant forDouble(double d) { |
| if (Double.compare(0.0D, d) == 0) { |
| return DOUBLE_0; |
| } |
| if (Double.compare(d, 1.0D) == 0) { |
| return DOUBLE_1; |
| } |
| return new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(d)); |
| } |
| |
| /** |
| * Creates a boxed float constant. |
| * |
| * @param f the float value to box |
| * @return a boxed copy of {@code value} |
| */ |
| static PrimitiveConstant forFloat(float f) { |
| if (Float.compare(f, 0.0F) == 0) { |
| return FLOAT_0; |
| } |
| if (Float.compare(f, 1.0F) == 0) { |
| return FLOAT_1; |
| } |
| return new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(f)); |
| } |
| |
| /** |
| * Creates a boxed long constant. |
| * |
| * @param i the long value to box |
| * @return a boxed copy of {@code value} |
| */ |
| static PrimitiveConstant forLong(long i) { |
| if (i == 0) { |
| return LONG_0; |
| } else if (i == 1) { |
| return LONG_1; |
| } else { |
| return new PrimitiveConstant(JavaKind.Long, i); |
| } |
| } |
| |
| /** |
| * Creates a boxed integer constant. |
| * |
| * @param i the integer value to box |
| * @return a boxed copy of {@code value} |
| */ |
| static PrimitiveConstant forInt(int i) { |
| switch (i) { |
| case -1: |
| return INT_MINUS_1; |
| case 0: |
| return INT_0; |
| case 1: |
| return INT_1; |
| case 2: |
| return INT_2; |
| default: |
| return new PrimitiveConstant(JavaKind.Int, i); |
| } |
| } |
| |
| /** |
| * Creates a boxed byte constant. |
| * |
| * @param i the byte value to box |
| * @return a boxed copy of {@code value} |
| */ |
| static PrimitiveConstant forByte(byte i) { |
| return new PrimitiveConstant(JavaKind.Byte, i); |
| } |
| |
| /** |
| * Creates a boxed boolean constant. |
| * |
| * @param i the boolean value to box |
| * @return a boxed copy of {@code value} |
| */ |
| static PrimitiveConstant forBoolean(boolean i) { |
| return i ? TRUE : FALSE; |
| } |
| |
| /** |
| * Creates a boxed char constant. |
| * |
| * @param i the char value to box |
| * @return a boxed copy of {@code value} |
| */ |
| static PrimitiveConstant forChar(char i) { |
| return new PrimitiveConstant(JavaKind.Char, i); |
| } |
| |
| /** |
| * Creates a boxed short constant. |
| * |
| * @param i the short value to box |
| * @return a boxed copy of {@code value} |
| */ |
| static PrimitiveConstant forShort(short i) { |
| return new PrimitiveConstant(JavaKind.Short, i); |
| } |
| |
| /** |
| * Creates a {@link JavaConstant} from a primitive integer of a certain kind. |
| */ |
| static PrimitiveConstant forIntegerKind(JavaKind kind, long i) { |
| switch (kind) { |
| case Boolean: |
| return forBoolean(i != 0); |
| case Byte: |
| return forByte((byte) i); |
| case Short: |
| return forShort((short) i); |
| case Char: |
| return forChar((char) i); |
| case Int: |
| return forInt((int) i); |
| case Long: |
| return forLong(i); |
| default: |
| throw new IllegalArgumentException("not an integer kind: " + kind); |
| } |
| } |
| |
| /** |
| * Creates a {@link JavaConstant} from a primitive integer of a certain width. |
| */ |
| static PrimitiveConstant forPrimitiveInt(int bits, long i) { |
| assert bits <= 64; |
| switch (bits) { |
| case 1: |
| return forBoolean(i != 0); |
| case 8: |
| return forByte((byte) i); |
| case 16: |
| return forShort((short) i); |
| case 32: |
| return forInt((int) i); |
| case 64: |
| return forLong(i); |
| default: |
| throw new IllegalArgumentException("unsupported integer width: " + bits); |
| } |
| } |
| |
| /** |
| * Creates a boxed constant for the given boxed primitive value. |
| * |
| * @param value the Java boxed value |
| * @return the primitive constant holding the {@code value} |
| */ |
| static PrimitiveConstant forBoxedPrimitive(Object value) { |
| if (value instanceof Boolean) { |
| return forBoolean((Boolean) value); |
| } else if (value instanceof Byte) { |
| return forByte((Byte) value); |
| } else if (value instanceof Character) { |
| return forChar((Character) value); |
| } else if (value instanceof Short) { |
| return forShort((Short) value); |
| } else if (value instanceof Integer) { |
| return forInt((Integer) value); |
| } else if (value instanceof Long) { |
| return forLong((Long) value); |
| } else if (value instanceof Float) { |
| return forFloat((Float) value); |
| } else if (value instanceof Double) { |
| return forDouble((Double) value); |
| } else { |
| return null; |
| } |
| } |
| |
| static PrimitiveConstant forIllegal() { |
| return new PrimitiveConstant(JavaKind.Illegal, 0); |
| } |
| |
| /** |
| * Returns a constant with the default value for the given kind. |
| */ |
| static JavaConstant defaultForKind(JavaKind kind) { |
| switch (kind) { |
| case Boolean: |
| return FALSE; |
| case Byte: |
| return forByte((byte) 0); |
| case Char: |
| return forChar((char) 0); |
| case Short: |
| return forShort((short) 0); |
| case Int: |
| return INT_0; |
| case Double: |
| return DOUBLE_0; |
| case Float: |
| return FLOAT_0; |
| case Long: |
| return LONG_0; |
| case Object: |
| return NULL_POINTER; |
| default: |
| throw new IllegalArgumentException(kind.toString()); |
| } |
| } |
| } |