diff graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java @ 15018:db4254246f9a

Remove Constant.forObject and Constant.asObject to improve compiler/VM separation
author Christian Wimmer <christian.wimmer@oracle.com>
date Mon, 07 Apr 2014 16:09:17 -0700
parents 82e4fe6fa525
children b862cf4381ef
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Mon Apr 07 23:35:41 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Mon Apr 07 16:09:17 2014 -0700
@@ -22,42 +22,40 @@
  */
 package com.oracle.graal.api.meta;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 /**
  * 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 Constant} instances that represent frequently used constant values, such as
  * {@link #NULL_OBJECT}.
  */
-public final class Constant extends Value {
+public abstract class Constant extends Value {
 
     private static final long serialVersionUID = -6355452536852663986L;
 
     private static final Constant[] INT_CONSTANT_CACHE = new Constant[100];
     static {
         for (int i = 0; i < INT_CONSTANT_CACHE.length; ++i) {
-            INT_CONSTANT_CACHE[i] = new Constant(Kind.Int, null, i);
+            INT_CONSTANT_CACHE[i] = new PrimitiveConstant(Kind.Int, i);
         }
     }
 
-    public static final Constant NULL_OBJECT = new Constant(Kind.Object, null, 0);
-    public static final Constant INT_MINUS_1 = new Constant(Kind.Int, null, -1);
+    public static final Constant NULL_OBJECT = new NullConstant();
+    public static final Constant INT_MINUS_1 = new PrimitiveConstant(Kind.Int, -1);
     public static final Constant INT_0 = forInt(0);
     public static final Constant INT_1 = forInt(1);
     public static final Constant INT_2 = forInt(2);
     public static final Constant INT_3 = forInt(3);
     public static final Constant INT_4 = forInt(4);
     public static final Constant INT_5 = forInt(5);
-    public static final Constant LONG_0 = new Constant(Kind.Long, null, 0L);
-    public static final Constant LONG_1 = new Constant(Kind.Long, null, 1L);
-    public static final Constant FLOAT_0 = new Constant(Kind.Float, null, Float.floatToRawIntBits(0.0F));
-    public static final Constant FLOAT_1 = new Constant(Kind.Float, null, Float.floatToRawIntBits(1.0F));
-    public static final Constant FLOAT_2 = new Constant(Kind.Float, null, Float.floatToRawIntBits(2.0F));
-    public static final Constant DOUBLE_0 = new Constant(Kind.Double, null, Double.doubleToRawLongBits(0.0D));
-    public static final Constant DOUBLE_1 = new Constant(Kind.Double, null, Double.doubleToRawLongBits(1.0D));
-    public static final Constant TRUE = new Constant(Kind.Boolean, null, 1L);
-    public static final Constant FALSE = new Constant(Kind.Boolean, null, 0L);
+    public static final Constant LONG_0 = new PrimitiveConstant(Kind.Long, 0L);
+    public static final Constant LONG_1 = new PrimitiveConstant(Kind.Long, 1L);
+    public static final Constant FLOAT_0 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(0.0F));
+    public static final Constant FLOAT_1 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(1.0F));
+    public static final Constant FLOAT_2 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(2.0F));
+    public static final Constant DOUBLE_0 = new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(0.0D));
+    public static final Constant DOUBLE_1 = new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(1.0D));
+    public static final Constant TRUE = new PrimitiveConstant(Kind.Boolean, 1L);
+    public static final Constant FALSE = new PrimitiveConstant(Kind.Boolean, 0L);
 
     static {
         assert FLOAT_0 != forFloat(-0.0F) : "Constant for 0.0f must be different from -0.0f";
@@ -65,56 +63,82 @@
         assert NULL_OBJECT.isNull();
     }
 
-    /**
-     * The boxed object value if {@code !kind.isObject()} otherwise the (possibly null)
-     * {@link #getPrimitiveAnnotation() annotation} for a primitive value.
-     */
-    private final Object object;
-
-    /**
-     * The boxed primitive value as a {@code long}. This is ignored iff {@code kind.isObject()}. For
-     * {@code float} and {@code double} values, this value is the result of
-     * {@link Float#floatToRawIntBits(float)} and {@link Double#doubleToRawLongBits(double)}
-     * respectively.
-     */
-    private final long primitive;
-
-    private Constant(Kind kind, Object object, long primitive) {
+    protected Constant(Kind kind) {
         super(kind);
-        this.object = object;
-        this.primitive = primitive;
-    }
-
-    /**
-     * Checks whether this constant is non-null.
-     * 
-     * @return {@code true} if this constant is a primitive, or an object constant that is not null
-     */
-    public boolean isNonNull() {
-        return getKind() != Kind.Object || object != null;
     }
 
     /**
      * Checks whether this constant is null.
-     * 
+     *
      * @return {@code true} if this constant is the null constant
      */
-    public boolean isNull() {
-        return getKind() == Kind.Object && object == null;
+    public abstract boolean isNull();
+
+    /**
+     * Checks whether this constant is non-null.
+     *
+     * @return {@code true} if this constant is a primitive, or an object constant that is not null
+     */
+    public final 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
      */
-    public boolean isDefaultForKind() {
-        return object == null && primitive == 0;
-    }
+    public abstract boolean isDefaultForKind();
+
+    /**
+     * Returns the value of this constant as a boxed Java value.
+     *
+     * @return the value of this constant
+     */
+    public abstract Object asBoxedPrimitive();
+
+    /**
+     * Returns the primitive int value this constant represents. The constant must have a
+     * {@link Kind#getStackKind()} of {@link Kind#Int}.
+     *
+     * @return the constant value
+     */
+    public abstract int asInt();
+
+    /**
+     * Returns the primitive boolean value this constant represents. The constant must have kind
+     * {@link Kind#Boolean}.
+     *
+     * @return the constant value
+     */
+    public abstract boolean asBoolean();
 
-    public long getPrimitive() {
-        assert getKind().isPrimitive();
-        return primitive;
+    /**
+     * Returns the primitive long value this constant represents. The constant must have kind
+     * {@link Kind#Long}, a {@link Kind#getStackKind()} of {@link Kind#Int}.
+     *
+     * @return the constant value
+     */
+    public abstract long asLong();
+
+    /**
+     * Returns the primitive float value this constant represents. The constant must have kind
+     * {@link Kind#Float}.
+     *
+     * @return the constant value
+     */
+    public abstract float asFloat();
+
+    /**
+     * Returns the primitive double value this constant represents. The constant must have kind
+     * {@link Kind#Double}.
+     *
+     * @return the constant value
+     */
+    public abstract double asDouble();
+
+    public String toValueString() {
+        return getKind().format(asBoxedPrimitive());
     }
 
     @Override
@@ -122,165 +146,13 @@
         if (getKind() == Kind.Illegal) {
             return "illegal";
         } else {
-            String annotationSuffix = "";
-            Object primitiveAnnotation = getPrimitiveAnnotation();
-            if (getKind() != Kind.Object && primitiveAnnotation != null) {
-                try {
-                    annotationSuffix = "{" + primitiveAnnotation + "}";
-                } catch (Throwable t) {
-                    annotationSuffix = "{" + getSimpleName(primitiveAnnotation.getClass(), true) + "@" + System.identityHashCode(primitiveAnnotation) + "}";
-                }
-            }
-            return getKind().getJavaName() + "[" + getKind().format(asBoxedValue()) + (getKind() != Kind.Object ? "|0x" + Long.toHexString(primitive) : "") + "]" + annotationSuffix;
+            return getKind().getJavaName() + "[" + toValueString() + "]";
         }
     }
 
     /**
-     * Returns the value of this constant as a boxed Java value.
-     * 
-     * @return the value of this constant
-     */
-    public Object asBoxedValue() {
-        switch (getKind()) {
-            case Byte:
-                return (byte) asInt();
-            case Boolean:
-                return asInt() == 0 ? Boolean.FALSE : Boolean.TRUE;
-            case Short:
-                return (short) primitive;
-            case Char:
-                return (char) primitive;
-            case Int:
-                return (int) primitive;
-            case Long:
-                return primitive;
-            case Float:
-                return asFloat();
-            case Double:
-                return asDouble();
-            case Object:
-                return object;
-            case Illegal:
-                return this;
-        }
-        throw new IllegalArgumentException();
-    }
-
-    private boolean valueEqual(Constant other, boolean ignoreKind) {
-        // must have equivalent kinds to be equal
-        if (!ignoreKind && getKind() != other.getKind()) {
-            return false;
-        }
-        if (getKind() == Kind.Object) {
-            return object == other.object;
-        }
-        return primitive == other.primitive && getPrimitiveAnnotation() == other.getPrimitiveAnnotation();
-    }
-
-    /**
-     * Returns the primitive int value this constant represents. The constant must have a
-     * {@link Kind#getStackKind()} of {@link Kind#Int}.
-     * 
-     * @return the constant value
-     */
-    public int asInt() {
-        assert getKind().getStackKind() == Kind.Int;
-        return (int) primitive;
-    }
-
-    /**
-     * Returns the primitive boolean value this constant represents. The constant must have kind
-     * {@link Kind#Boolean}.
-     * 
-     * @return the constant value
-     */
-    public boolean asBoolean() {
-        assert getKind() == Kind.Boolean;
-        return primitive != 0L;
-    }
-
-    /**
-     * Returns the primitive long value this constant represents. The constant must have kind
-     * {@link Kind#Long}, a {@link Kind#getStackKind()} of {@link Kind#Int}.
-     * 
-     * @return the constant value
-     */
-    public long asLong() {
-        assert getKind().isNumericInteger();
-        return primitive;
-    }
-
-    /**
-     * Returns the primitive float value this constant represents. The constant must have kind
-     * {@link Kind#Float}.
-     * 
-     * @return the constant value
-     */
-    public float asFloat() {
-        assert getKind() == Kind.Float;
-        return Float.intBitsToFloat((int) primitive);
-    }
-
-    /**
-     * Returns the primitive double value this constant represents. The constant must have kind
-     * {@link Kind#Double}.
-     * 
-     * @return the constant value
-     */
-    public double asDouble() {
-        assert getKind() == Kind.Double;
-        return Double.longBitsToDouble(primitive);
-    }
-
-    /**
-     * Returns the object reference this constant represents. The constant must have kind
-     * {@link Kind#Object}.
-     * 
-     * @return the constant value
-     */
-    public Object asObject() {
-        assert getKind() == Kind.Object;
-        return object;
-    }
-
-    /**
-     * Gets the annotation (if any) associated with this constant.
-     * 
-     * @return null if this constant is not primitive or has no annotation
-     */
-    public Object getPrimitiveAnnotation() {
-        return getKind() == Kind.Object ? null : object;
-    }
-
-    /**
-     * Computes the hashcode of this constant.
-     * 
-     * @return a suitable hashcode for this constant
-     */
-    @Override
-    public int hashCode() {
-        if (getKind() == Kind.Object) {
-            return System.identityHashCode(object);
-        }
-        return (int) primitive * getKind().ordinal();
-    }
-
-    /**
-     * Checks whether this constant equals another object. This is only true if the other object is
-     * a constant that has the same {@linkplain #getKind() kind}, value and
-     * {@link #getPrimitiveAnnotation() annotation}.
-     * 
-     * @param o the object to compare equality
-     * @return {@code true} if this constant is equivalent to the specified object
-     */
-    @Override
-    public boolean equals(Object o) {
-        return o == this || o instanceof Constant && valueEqual((Constant) o, false);
-    }
-
-    /**
      * Creates a boxed double constant.
-     * 
+     *
      * @param d the double value to box
      * @return a boxed copy of {@code value}
      */
@@ -291,12 +163,12 @@
         if (Double.compare(d, 1.0D) == 0) {
             return DOUBLE_1;
         }
-        return new Constant(Kind.Double, null, Double.doubleToRawLongBits(d));
+        return new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(d));
     }
 
     /**
      * Creates a boxed float constant.
-     * 
+     *
      * @param f the float value to box
      * @return a boxed copy of {@code value}
      */
@@ -310,22 +182,22 @@
         if (Float.compare(f, 2.0F) == 0) {
             return FLOAT_2;
         }
-        return new Constant(Kind.Float, null, Float.floatToRawIntBits(f));
+        return new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(f));
     }
 
     /**
      * Creates a boxed long constant.
-     * 
+     *
      * @param i the long value to box
      * @return a boxed copy of {@code value}
      */
     public static Constant forLong(long i) {
-        return i == 0 ? LONG_0 : i == 1 ? LONG_1 : new Constant(Kind.Long, null, i);
+        return i == 0 ? LONG_0 : i == 1 ? LONG_1 : new PrimitiveConstant(Kind.Long, i);
     }
 
     /**
      * Creates a boxed integer constant.
-     * 
+     *
      * @param i the integer value to box
      * @return a boxed copy of {@code value}
      */
@@ -336,22 +208,22 @@
         if (i >= 0 && i < INT_CONSTANT_CACHE.length) {
             return INT_CONSTANT_CACHE[i];
         }
-        return new Constant(Kind.Int, null, i);
+        return new PrimitiveConstant(Kind.Int, i);
     }
 
     /**
      * Creates a boxed byte constant.
-     * 
+     *
      * @param i the byte value to box
      * @return a boxed copy of {@code value}
      */
     public static Constant forByte(byte i) {
-        return new Constant(Kind.Byte, null, i);
+        return new PrimitiveConstant(Kind.Byte, i);
     }
 
     /**
      * Creates a boxed boolean constant.
-     * 
+     *
      * @param i the boolean value to box
      * @return a boxed copy of {@code value}
      */
@@ -361,52 +233,33 @@
 
     /**
      * Creates a boxed char constant.
-     * 
+     *
      * @param i the char value to box
      * @return a boxed copy of {@code value}
      */
     public static Constant forChar(char i) {
-        return new Constant(Kind.Char, null, i);
+        return new PrimitiveConstant(Kind.Char, i);
     }
 
     /**
      * Creates a boxed short constant.
-     * 
+     *
      * @param i the short value to box
      * @return a boxed copy of {@code value}
      */
     public static Constant forShort(short i) {
-        return new Constant(Kind.Short, null, i);
+        return new PrimitiveConstant(Kind.Short, i);
     }
 
     /**
-     * Creates a boxed object constant.
-     * 
-     * @param o the object value to box
-     * @return a boxed copy of {@code value}
+     * Creates a {@link Constant} from a primitive integer of a certain kind.
      */
-    public static Constant forObject(Object o) {
-        if (o == null) {
-            return NULL_OBJECT;
-        }
-        return new Constant(Kind.Object, o, 0L);
-    }
-
-    /**
-     * Creates an annotated int or long constant. An annotation enables a client to associate some
-     * extra semantic or debugging information with a primitive. An annotated primitive constant is
-     * never {@linkplain #equals(Object) equal} to a non-annotated constant.
-     * 
-     * @param kind the type of this constant
-     * @param i the value of this constant
-     * @param annotation an arbitrary non-null object
-     */
-    public static Constant forIntegerKind(Kind kind, long i, Object annotation) {
+    public static Constant forIntegerKind(Kind kind, long i) {
         switch (kind) {
             case Int:
-                return new Constant(kind, annotation, (int) i);
+                return new PrimitiveConstant(kind, (int) i);
             case Long:
-                return new Constant(kind, annotation, i);
+                return new PrimitiveConstant(kind, i);
             default:
                 throw new IllegalArgumentException("not an integer kind: " + kind);
         }
@@ -418,47 +271,42 @@
     public static Constant forPrimitiveInt(int bits, long i) {
         assert bits <= 64;
         if (bits > 32) {
-            return new Constant(Kind.Long, null, i);
+            return new PrimitiveConstant(Kind.Long, i);
         } else {
-            return new Constant(Kind.Int, null, (int) i);
+            return new PrimitiveConstant(Kind.Int, (int) i);
         }
     }
 
     /**
-     * Creates a boxed constant for the given kind from an Object. The object needs to be of the
-     * Java boxed type corresponding to the kind.
-     * 
-     * @param kind the kind of the constant to create
-     * @param value the Java boxed value: a {@link Byte} instance for {@link Kind#Byte}, etc.
-     * @return the boxed copy of {@code value}
+     * Creates a boxed constant for the given boxed primitive value.
+     *
+     * @param value the Java boxed value
+     * @return the primitive constant holding the {@code value}
      */
-    public static Constant forBoxed(Kind kind, Object value) {
-        switch (kind) {
-            case Boolean:
-                return forBoolean((Boolean) value);
-            case Byte:
-                return forByte((Byte) value);
-            case Char:
-                return forChar((Character) value);
-            case Short:
-                return forShort((Short) value);
-            case Int:
-                return forInt((Integer) value);
-            case Long:
-                return forLong((Long) value);
-            case Float:
-                return forFloat((Float) value);
-            case Double:
-                return forDouble((Double) value);
-            case Object:
-                return forObject(value);
-            default:
-                throw new RuntimeException("cannot create Constant for boxed " + kind + " value");
+    public static Constant 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;
         }
     }
 
     public static Constant forIllegal() {
-        return new Constant(Kind.Illegal, null, 0);
+        return new PrimitiveConstant(Kind.Illegal, 0);
     }
 
     /**