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 }