1 /*
   2  * Copyright (c) 2009, 2015, 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 package jdk.vm.ci.meta;
  24 
  25 /**
  26  * Represents a constant (boxed) value, such as an integer, floating point number, or object
  27  * reference, within the compiler and across the compiler/runtime interface. Exports a set of
  28  * {@code JavaConstant} instances that represent frequently used constant values, such as
  29  * {@link #NULL_POINTER}.
  30  */
  31 public interface JavaConstant extends Constant, JavaValue {
  32     /*
  33      * Using a larger cache for integers leads to only a slight increase in cache hit ratio which is
  34      * not enough to justify the impact on startup time.
  35      */
  36     JavaConstant NULL_POINTER = new NullConstant();
  37     PrimitiveConstant INT_MINUS_1 = new PrimitiveConstant(JavaKind.Int, -1);
  38     PrimitiveConstant INT_0 = new PrimitiveConstant(JavaKind.Int, 0);
  39     PrimitiveConstant INT_1 = new PrimitiveConstant(JavaKind.Int, 1);
  40     PrimitiveConstant INT_2 = new PrimitiveConstant(JavaKind.Int, 2);
  41     PrimitiveConstant LONG_0 = new PrimitiveConstant(JavaKind.Long, 0L);
  42     PrimitiveConstant LONG_1 = new PrimitiveConstant(JavaKind.Long, 1L);
  43     PrimitiveConstant FLOAT_0 = new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(0.0F));
  44     PrimitiveConstant FLOAT_1 = new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(1.0F));
  45     PrimitiveConstant DOUBLE_0 = new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(0.0D));
  46     PrimitiveConstant DOUBLE_1 = new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(1.0D));
  47     PrimitiveConstant TRUE = new PrimitiveConstant(JavaKind.Boolean, 1L);
  48     PrimitiveConstant FALSE = new PrimitiveConstant(JavaKind.Boolean, 0L);
  49 
  50     /**
  51      * Returns the Java kind of this constant.
  52      */
  53     JavaKind getJavaKind();
  54 
  55     /**
  56      * Checks whether this constant is null.
  57      *
  58      * @return {@code true} if this constant is the null constant
  59      */
  60     boolean isNull();
  61 
  62     static boolean isNull(Constant c) {
  63         if (c instanceof JavaConstant) {
  64             return ((JavaConstant) c).isNull();
  65         } else {
  66             return false;
  67         }
  68     }
  69 
  70     /**
  71      * Checks whether this constant is non-null.
  72      *
  73      * @return {@code true} if this constant is a primitive, or an object constant that is not null
  74      */
  75     default boolean isNonNull() {
  76         return !isNull();
  77     }
  78 
  79     /**
  80      * Checks whether this constant is the default value for its kind (null, 0, 0.0, false).
  81      *
  82      * @return {@code true} if this constant is the default value for its kind
  83      */
  84     boolean isDefaultForKind();
  85 
  86     /**
  87      * Returns the value of this constant as a boxed Java value.
  88      *
  89      * @return the value of this constant
  90      */
  91     Object asBoxedPrimitive();
  92 
  93     /**
  94      * Returns the primitive int value this constant represents. The constant must have a
  95      * {@link JavaKind#getStackKind()} of {@link JavaKind#Int}.
  96      *
  97      * @return the constant value
  98      */
  99     int asInt();
 100 
 101     /**
 102      * Returns the primitive boolean value this constant represents. The constant must have kind
 103      * {@link JavaKind#Boolean}.
 104      *
 105      * @return the constant value
 106      */
 107     boolean asBoolean();
 108 
 109     /**
 110      * Returns the primitive long value this constant represents. The constant must have kind
 111      * {@link JavaKind#Long}, a {@link JavaKind#getStackKind()} of {@link JavaKind#Int}.
 112      *
 113      * @return the constant value
 114      */
 115     long asLong();
 116 
 117     /**
 118      * Returns the primitive float value this constant represents. The constant must have kind
 119      * {@link JavaKind#Float}.
 120      *
 121      * @return the constant value
 122      */
 123     float asFloat();
 124 
 125     /**
 126      * Returns the primitive double value this constant represents. The constant must have kind
 127      * {@link JavaKind#Double}.
 128      *
 129      * @return the constant value
 130      */
 131     double asDouble();
 132 
 133     default String toValueString() {
 134         if (getJavaKind() == JavaKind.Illegal) {
 135             return "illegal";
 136         } else {
 137             return getJavaKind().format(asBoxedPrimitive());
 138         }
 139     }
 140 
 141     static String toString(JavaConstant constant) {
 142         if (constant.getJavaKind() == JavaKind.Illegal) {
 143             return "illegal";
 144         } else {
 145             return constant.getJavaKind().getJavaName() + "[" + constant.toValueString() + "]";
 146         }
 147     }
 148 
 149     /**
 150      * Creates a boxed double constant.
 151      *
 152      * @param d the double value to box
 153      * @return a boxed copy of {@code value}
 154      */
 155     static PrimitiveConstant forDouble(double d) {
 156         if (Double.compare(0.0D, d) == 0) {
 157             return DOUBLE_0;
 158         }
 159         if (Double.compare(d, 1.0D) == 0) {
 160             return DOUBLE_1;
 161         }
 162         return new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(d));
 163     }
 164 
 165     /**
 166      * Creates a boxed float constant.
 167      *
 168      * @param f the float value to box
 169      * @return a boxed copy of {@code value}
 170      */
 171     static PrimitiveConstant forFloat(float f) {
 172         if (Float.compare(f, 0.0F) == 0) {
 173             return FLOAT_0;
 174         }
 175         if (Float.compare(f, 1.0F) == 0) {
 176             return FLOAT_1;
 177         }
 178         return new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(f));
 179     }
 180 
 181     /**
 182      * Creates a boxed long constant.
 183      *
 184      * @param i the long value to box
 185      * @return a boxed copy of {@code value}
 186      */
 187     static PrimitiveConstant forLong(long i) {
 188         if (i == 0) {
 189             return LONG_0;
 190         } else if (i == 1) {
 191             return LONG_1;
 192         } else {
 193             return new PrimitiveConstant(JavaKind.Long, i);
 194         }
 195     }
 196 
 197     /**
 198      * Creates a boxed integer constant.
 199      *
 200      * @param i the integer value to box
 201      * @return a boxed copy of {@code value}
 202      */
 203     static PrimitiveConstant forInt(int i) {
 204         switch (i) {
 205             case -1:
 206                 return INT_MINUS_1;
 207             case 0:
 208                 return INT_0;
 209             case 1:
 210                 return INT_1;
 211             case 2:
 212                 return INT_2;
 213             default:
 214                 return new PrimitiveConstant(JavaKind.Int, i);
 215         }
 216     }
 217 
 218     /**
 219      * Creates a boxed byte constant.
 220      *
 221      * @param i the byte value to box
 222      * @return a boxed copy of {@code value}
 223      */
 224     static PrimitiveConstant forByte(byte i) {
 225         return new PrimitiveConstant(JavaKind.Byte, i);
 226     }
 227 
 228     /**
 229      * Creates a boxed boolean constant.
 230      *
 231      * @param i the boolean value to box
 232      * @return a boxed copy of {@code value}
 233      */
 234     static PrimitiveConstant forBoolean(boolean i) {
 235         return i ? TRUE : FALSE;
 236     }
 237 
 238     /**
 239      * Creates a boxed char constant.
 240      *
 241      * @param i the char value to box
 242      * @return a boxed copy of {@code value}
 243      */
 244     static PrimitiveConstant forChar(char i) {
 245         return new PrimitiveConstant(JavaKind.Char, i);
 246     }
 247 
 248     /**
 249      * Creates a boxed short constant.
 250      *
 251      * @param i the short value to box
 252      * @return a boxed copy of {@code value}
 253      */
 254     static PrimitiveConstant forShort(short i) {
 255         return new PrimitiveConstant(JavaKind.Short, i);
 256     }
 257 
 258     /**
 259      * Creates a {@link JavaConstant} from a primitive integer of a certain kind.
 260      */
 261     static PrimitiveConstant forIntegerKind(JavaKind kind, long i) {
 262         switch (kind) {
 263             case Boolean:
 264                 return forBoolean(i != 0);
 265             case Byte:
 266                 return forByte((byte) i);
 267             case Short:
 268                 return forShort((short) i);
 269             case Char:
 270                 return forChar((char) i);
 271             case Int:
 272                 return forInt((int) i);
 273             case Long:
 274                 return forLong(i);
 275             default:
 276                 throw new IllegalArgumentException("not an integer kind: " + kind);
 277         }
 278     }
 279 
 280     /**
 281      * Creates a {@link JavaConstant} from a primitive integer of a certain width.
 282      */
 283     static PrimitiveConstant forPrimitiveInt(int bits, long i) {
 284         assert bits <= 64;
 285         switch (bits) {
 286             case 1:
 287                 return forBoolean(i != 0);
 288             case 8:
 289                 return forByte((byte) i);
 290             case 16:
 291                 return forShort((short) i);
 292             case 32:
 293                 return forInt((int) i);
 294             case 64:
 295                 return forLong(i);
 296             default:
 297                 throw new IllegalArgumentException("unsupported integer width: " + bits);
 298         }
 299     }
 300 
 301     /**
 302      * Creates a boxed constant for the given boxed primitive value.
 303      *
 304      * @param value the Java boxed value
 305      * @return the primitive constant holding the {@code value}
 306      */
 307     static PrimitiveConstant forBoxedPrimitive(Object value) {
 308         if (value instanceof Boolean) {
 309             return forBoolean((Boolean) value);
 310         } else if (value instanceof Byte) {
 311             return forByte((Byte) value);
 312         } else if (value instanceof Character) {
 313             return forChar((Character) value);
 314         } else if (value instanceof Short) {
 315             return forShort((Short) value);
 316         } else if (value instanceof Integer) {
 317             return forInt((Integer) value);
 318         } else if (value instanceof Long) {
 319             return forLong((Long) value);
 320         } else if (value instanceof Float) {
 321             return forFloat((Float) value);
 322         } else if (value instanceof Double) {
 323             return forDouble((Double) value);
 324         } else {
 325             return null;
 326         }
 327     }
 328 
 329     static PrimitiveConstant forIllegal() {
 330         return new PrimitiveConstant(JavaKind.Illegal, 0);
 331     }
 332 
 333     /**
 334      * Returns a constant with the default value for the given kind.
 335      */
 336     static JavaConstant defaultForKind(JavaKind kind) {
 337         switch (kind) {
 338             case Boolean:
 339                 return FALSE;
 340             case Byte:
 341                 return forByte((byte) 0);
 342             case Char:
 343                 return forChar((char) 0);
 344             case Short:
 345                 return forShort((short) 0);
 346             case Int:
 347                 return INT_0;
 348             case Double:
 349                 return DOUBLE_0;
 350             case Float:
 351                 return FLOAT_0;
 352             case Long:
 353                 return LONG_0;
 354             case Object:
 355                 return NULL_POINTER;
 356             default:
 357                 throw new IllegalArgumentException(kind.toString());
 358         }
 359     }
 360 
 361     /**
 362      * Returns the zero value for a given numeric kind.
 363      */
 364     static JavaConstant zero(JavaKind kind) {
 365         switch (kind) {
 366             case Boolean:
 367                 return FALSE;
 368             case Byte:
 369                 return forByte((byte) 0);
 370             case Char:
 371                 return forChar((char) 0);
 372             case Double:
 373                 return DOUBLE_0;
 374             case Float:
 375                 return FLOAT_0;
 376             case Int:
 377                 return INT_0;
 378             case Long:
 379                 return LONG_0;
 380             case Short:
 381                 return forShort((short) 0);
 382             default:
 383                 throw new IllegalArgumentException(kind.toString());
 384         }
 385     }
 386 
 387     /**
 388      * Returns the one value for a given numeric kind.
 389      */
 390     static JavaConstant one(JavaKind kind) {
 391         switch (kind) {
 392             case Boolean:
 393                 return TRUE;
 394             case Byte:
 395                 return forByte((byte) 1);
 396             case Char:
 397                 return forChar((char) 1);
 398             case Double:
 399                 return DOUBLE_1;
 400             case Float:
 401                 return FLOAT_1;
 402             case Int:
 403                 return INT_1;
 404             case Long:
 405                 return LONG_1;
 406             case Short:
 407                 return forShort((short) 1);
 408             default:
 409                 throw new IllegalArgumentException(kind.toString());
 410         }
 411     }
 412 
 413     /**
 414      * Adds two numeric constants.
 415      */
 416     static JavaConstant add(JavaConstant x, JavaConstant y) {
 417         assert x.getJavaKind() == y.getJavaKind();
 418         switch (x.getJavaKind()) {
 419             case Byte:
 420                 return forByte((byte) (x.asInt() + y.asInt()));
 421             case Char:
 422                 return forChar((char) (x.asInt() + y.asInt()));
 423             case Double:
 424                 return forDouble(x.asDouble() + y.asDouble());
 425             case Float:
 426                 return forFloat(x.asFloat() + y.asFloat());
 427             case Int:
 428                 return forInt(x.asInt() + y.asInt());
 429             case Long:
 430                 return forLong(x.asLong() + y.asLong());
 431             case Short:
 432                 return forShort((short) (x.asInt() + y.asInt()));
 433             default:
 434                 throw new IllegalArgumentException(x.getJavaKind().toString());
 435         }
 436     }
 437 
 438     /**
 439      * Multiplies two numeric constants.
 440      */
 441     static PrimitiveConstant mul(JavaConstant x, JavaConstant y) {
 442         assert x.getJavaKind() == y.getJavaKind();
 443         switch (x.getJavaKind()) {
 444             case Byte:
 445                 return forByte((byte) (x.asInt() * y.asInt()));
 446             case Char:
 447                 return forChar((char) (x.asInt() * y.asInt()));
 448             case Double:
 449                 return forDouble(x.asDouble() * y.asDouble());
 450             case Float:
 451                 return forFloat(x.asFloat() * y.asFloat());
 452             case Int:
 453                 return forInt(x.asInt() * y.asInt());
 454             case Long:
 455                 return forLong(x.asLong() * y.asLong());
 456             case Short:
 457                 return forShort((short) (x.asInt() * y.asInt()));
 458             default:
 459                 throw new IllegalArgumentException(x.getJavaKind().toString());
 460         }
 461     }
 462 }