comparison 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
comparison
equal deleted inserted replaced
15017:ff5660822992 15018:db4254246f9a
20 * or visit www.oracle.com if you need additional information or have any 20 * or visit www.oracle.com if you need additional information or have any
21 * questions. 21 * questions.
22 */ 22 */
23 package com.oracle.graal.api.meta; 23 package com.oracle.graal.api.meta;
24 24
25 import static com.oracle.graal.api.meta.MetaUtil.*;
26
27 /** 25 /**
28 * Represents a constant (boxed) value, such as an integer, floating point number, or object 26 * Represents a constant (boxed) value, such as an integer, floating point number, or object
29 * reference, within the compiler and across the compiler/runtime interface. Exports a set of 27 * reference, within the compiler and across the compiler/runtime interface. Exports a set of
30 * {@code Constant} instances that represent frequently used constant values, such as 28 * {@code Constant} instances that represent frequently used constant values, such as
31 * {@link #NULL_OBJECT}. 29 * {@link #NULL_OBJECT}.
32 */ 30 */
33 public final class Constant extends Value { 31 public abstract class Constant extends Value {
34 32
35 private static final long serialVersionUID = -6355452536852663986L; 33 private static final long serialVersionUID = -6355452536852663986L;
36 34
37 private static final Constant[] INT_CONSTANT_CACHE = new Constant[100]; 35 private static final Constant[] INT_CONSTANT_CACHE = new Constant[100];
38 static { 36 static {
39 for (int i = 0; i < INT_CONSTANT_CACHE.length; ++i) { 37 for (int i = 0; i < INT_CONSTANT_CACHE.length; ++i) {
40 INT_CONSTANT_CACHE[i] = new Constant(Kind.Int, null, i); 38 INT_CONSTANT_CACHE[i] = new PrimitiveConstant(Kind.Int, i);
41 } 39 }
42 } 40 }
43 41
44 public static final Constant NULL_OBJECT = new Constant(Kind.Object, null, 0); 42 public static final Constant NULL_OBJECT = new NullConstant();
45 public static final Constant INT_MINUS_1 = new Constant(Kind.Int, null, -1); 43 public static final Constant INT_MINUS_1 = new PrimitiveConstant(Kind.Int, -1);
46 public static final Constant INT_0 = forInt(0); 44 public static final Constant INT_0 = forInt(0);
47 public static final Constant INT_1 = forInt(1); 45 public static final Constant INT_1 = forInt(1);
48 public static final Constant INT_2 = forInt(2); 46 public static final Constant INT_2 = forInt(2);
49 public static final Constant INT_3 = forInt(3); 47 public static final Constant INT_3 = forInt(3);
50 public static final Constant INT_4 = forInt(4); 48 public static final Constant INT_4 = forInt(4);
51 public static final Constant INT_5 = forInt(5); 49 public static final Constant INT_5 = forInt(5);
52 public static final Constant LONG_0 = new Constant(Kind.Long, null, 0L); 50 public static final Constant LONG_0 = new PrimitiveConstant(Kind.Long, 0L);
53 public static final Constant LONG_1 = new Constant(Kind.Long, null, 1L); 51 public static final Constant LONG_1 = new PrimitiveConstant(Kind.Long, 1L);
54 public static final Constant FLOAT_0 = new Constant(Kind.Float, null, Float.floatToRawIntBits(0.0F)); 52 public static final Constant FLOAT_0 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(0.0F));
55 public static final Constant FLOAT_1 = new Constant(Kind.Float, null, Float.floatToRawIntBits(1.0F)); 53 public static final Constant FLOAT_1 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(1.0F));
56 public static final Constant FLOAT_2 = new Constant(Kind.Float, null, Float.floatToRawIntBits(2.0F)); 54 public static final Constant FLOAT_2 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(2.0F));
57 public static final Constant DOUBLE_0 = new Constant(Kind.Double, null, Double.doubleToRawLongBits(0.0D)); 55 public static final Constant DOUBLE_0 = new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(0.0D));
58 public static final Constant DOUBLE_1 = new Constant(Kind.Double, null, Double.doubleToRawLongBits(1.0D)); 56 public static final Constant DOUBLE_1 = new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(1.0D));
59 public static final Constant TRUE = new Constant(Kind.Boolean, null, 1L); 57 public static final Constant TRUE = new PrimitiveConstant(Kind.Boolean, 1L);
60 public static final Constant FALSE = new Constant(Kind.Boolean, null, 0L); 58 public static final Constant FALSE = new PrimitiveConstant(Kind.Boolean, 0L);
61 59
62 static { 60 static {
63 assert FLOAT_0 != forFloat(-0.0F) : "Constant for 0.0f must be different from -0.0f"; 61 assert FLOAT_0 != forFloat(-0.0F) : "Constant for 0.0f must be different from -0.0f";
64 assert DOUBLE_0 != forDouble(-0.0d) : "Constant for 0.0d must be different from -0.0d"; 62 assert DOUBLE_0 != forDouble(-0.0d) : "Constant for 0.0d must be different from -0.0d";
65 assert NULL_OBJECT.isNull(); 63 assert NULL_OBJECT.isNull();
66 } 64 }
67 65
68 /** 66 protected Constant(Kind kind) {
69 * The boxed object value if {@code !kind.isObject()} otherwise the (possibly null)
70 * {@link #getPrimitiveAnnotation() annotation} for a primitive value.
71 */
72 private final Object object;
73
74 /**
75 * The boxed primitive value as a {@code long}. This is ignored iff {@code kind.isObject()}. For
76 * {@code float} and {@code double} values, this value is the result of
77 * {@link Float#floatToRawIntBits(float)} and {@link Double#doubleToRawLongBits(double)}
78 * respectively.
79 */
80 private final long primitive;
81
82 private Constant(Kind kind, Object object, long primitive) {
83 super(kind); 67 super(kind);
84 this.object = object; 68 }
85 this.primitive = primitive; 69
86 } 70 /**
71 * Checks whether this constant is null.
72 *
73 * @return {@code true} if this constant is the null constant
74 */
75 public abstract boolean isNull();
87 76
88 /** 77 /**
89 * Checks whether this constant is non-null. 78 * Checks whether this constant is non-null.
90 * 79 *
91 * @return {@code true} if this constant is a primitive, or an object constant that is not null 80 * @return {@code true} if this constant is a primitive, or an object constant that is not null
92 */ 81 */
93 public boolean isNonNull() { 82 public final boolean isNonNull() {
94 return getKind() != Kind.Object || object != null; 83 return !isNull();
95 }
96
97 /**
98 * Checks whether this constant is null.
99 *
100 * @return {@code true} if this constant is the null constant
101 */
102 public boolean isNull() {
103 return getKind() == Kind.Object && object == null;
104 } 84 }
105 85
106 /** 86 /**
107 * Checks whether this constant is the default value for its kind (null, 0, 0.0, false). 87 * Checks whether this constant is the default value for its kind (null, 0, 0.0, false).
108 * 88 *
109 * @return {@code true} if this constant is the default value for its kind 89 * @return {@code true} if this constant is the default value for its kind
110 */ 90 */
111 public boolean isDefaultForKind() { 91 public abstract boolean isDefaultForKind();
112 return object == null && primitive == 0; 92
113 } 93 /**
114 94 * Returns the value of this constant as a boxed Java value.
115 public long getPrimitive() { 95 *
116 assert getKind().isPrimitive(); 96 * @return the value of this constant
117 return primitive; 97 */
98 public abstract Object asBoxedPrimitive();
99
100 /**
101 * Returns the primitive int value this constant represents. The constant must have a
102 * {@link Kind#getStackKind()} of {@link Kind#Int}.
103 *
104 * @return the constant value
105 */
106 public abstract int asInt();
107
108 /**
109 * Returns the primitive boolean value this constant represents. The constant must have kind
110 * {@link Kind#Boolean}.
111 *
112 * @return the constant value
113 */
114 public abstract boolean asBoolean();
115
116 /**
117 * Returns the primitive long value this constant represents. The constant must have kind
118 * {@link Kind#Long}, a {@link Kind#getStackKind()} of {@link Kind#Int}.
119 *
120 * @return the constant value
121 */
122 public abstract long asLong();
123
124 /**
125 * Returns the primitive float value this constant represents. The constant must have kind
126 * {@link Kind#Float}.
127 *
128 * @return the constant value
129 */
130 public abstract float asFloat();
131
132 /**
133 * Returns the primitive double value this constant represents. The constant must have kind
134 * {@link Kind#Double}.
135 *
136 * @return the constant value
137 */
138 public abstract double asDouble();
139
140 public String toValueString() {
141 return getKind().format(asBoxedPrimitive());
118 } 142 }
119 143
120 @Override 144 @Override
121 public String toString() { 145 public String toString() {
122 if (getKind() == Kind.Illegal) { 146 if (getKind() == Kind.Illegal) {
123 return "illegal"; 147 return "illegal";
124 } else { 148 } else {
125 String annotationSuffix = ""; 149 return getKind().getJavaName() + "[" + toValueString() + "]";
126 Object primitiveAnnotation = getPrimitiveAnnotation(); 150 }
127 if (getKind() != Kind.Object && primitiveAnnotation != null) {
128 try {
129 annotationSuffix = "{" + primitiveAnnotation + "}";
130 } catch (Throwable t) {
131 annotationSuffix = "{" + getSimpleName(primitiveAnnotation.getClass(), true) + "@" + System.identityHashCode(primitiveAnnotation) + "}";
132 }
133 }
134 return getKind().getJavaName() + "[" + getKind().format(asBoxedValue()) + (getKind() != Kind.Object ? "|0x" + Long.toHexString(primitive) : "") + "]" + annotationSuffix;
135 }
136 }
137
138 /**
139 * Returns the value of this constant as a boxed Java value.
140 *
141 * @return the value of this constant
142 */
143 public Object asBoxedValue() {
144 switch (getKind()) {
145 case Byte:
146 return (byte) asInt();
147 case Boolean:
148 return asInt() == 0 ? Boolean.FALSE : Boolean.TRUE;
149 case Short:
150 return (short) primitive;
151 case Char:
152 return (char) primitive;
153 case Int:
154 return (int) primitive;
155 case Long:
156 return primitive;
157 case Float:
158 return asFloat();
159 case Double:
160 return asDouble();
161 case Object:
162 return object;
163 case Illegal:
164 return this;
165 }
166 throw new IllegalArgumentException();
167 }
168
169 private boolean valueEqual(Constant other, boolean ignoreKind) {
170 // must have equivalent kinds to be equal
171 if (!ignoreKind && getKind() != other.getKind()) {
172 return false;
173 }
174 if (getKind() == Kind.Object) {
175 return object == other.object;
176 }
177 return primitive == other.primitive && getPrimitiveAnnotation() == other.getPrimitiveAnnotation();
178 }
179
180 /**
181 * Returns the primitive int value this constant represents. The constant must have a
182 * {@link Kind#getStackKind()} of {@link Kind#Int}.
183 *
184 * @return the constant value
185 */
186 public int asInt() {
187 assert getKind().getStackKind() == Kind.Int;
188 return (int) primitive;
189 }
190
191 /**
192 * Returns the primitive boolean value this constant represents. The constant must have kind
193 * {@link Kind#Boolean}.
194 *
195 * @return the constant value
196 */
197 public boolean asBoolean() {
198 assert getKind() == Kind.Boolean;
199 return primitive != 0L;
200 }
201
202 /**
203 * Returns the primitive long value this constant represents. The constant must have kind
204 * {@link Kind#Long}, a {@link Kind#getStackKind()} of {@link Kind#Int}.
205 *
206 * @return the constant value
207 */
208 public long asLong() {
209 assert getKind().isNumericInteger();
210 return primitive;
211 }
212
213 /**
214 * Returns the primitive float value this constant represents. The constant must have kind
215 * {@link Kind#Float}.
216 *
217 * @return the constant value
218 */
219 public float asFloat() {
220 assert getKind() == Kind.Float;
221 return Float.intBitsToFloat((int) primitive);
222 }
223
224 /**
225 * Returns the primitive double value this constant represents. The constant must have kind
226 * {@link Kind#Double}.
227 *
228 * @return the constant value
229 */
230 public double asDouble() {
231 assert getKind() == Kind.Double;
232 return Double.longBitsToDouble(primitive);
233 }
234
235 /**
236 * Returns the object reference this constant represents. The constant must have kind
237 * {@link Kind#Object}.
238 *
239 * @return the constant value
240 */
241 public Object asObject() {
242 assert getKind() == Kind.Object;
243 return object;
244 }
245
246 /**
247 * Gets the annotation (if any) associated with this constant.
248 *
249 * @return null if this constant is not primitive or has no annotation
250 */
251 public Object getPrimitiveAnnotation() {
252 return getKind() == Kind.Object ? null : object;
253 }
254
255 /**
256 * Computes the hashcode of this constant.
257 *
258 * @return a suitable hashcode for this constant
259 */
260 @Override
261 public int hashCode() {
262 if (getKind() == Kind.Object) {
263 return System.identityHashCode(object);
264 }
265 return (int) primitive * getKind().ordinal();
266 }
267
268 /**
269 * Checks whether this constant equals another object. This is only true if the other object is
270 * a constant that has the same {@linkplain #getKind() kind}, value and
271 * {@link #getPrimitiveAnnotation() annotation}.
272 *
273 * @param o the object to compare equality
274 * @return {@code true} if this constant is equivalent to the specified object
275 */
276 @Override
277 public boolean equals(Object o) {
278 return o == this || o instanceof Constant && valueEqual((Constant) o, false);
279 } 151 }
280 152
281 /** 153 /**
282 * Creates a boxed double constant. 154 * Creates a boxed double constant.
283 * 155 *
284 * @param d the double value to box 156 * @param d the double value to box
285 * @return a boxed copy of {@code value} 157 * @return a boxed copy of {@code value}
286 */ 158 */
287 public static Constant forDouble(double d) { 159 public static Constant forDouble(double d) {
288 if (Double.compare(0.0D, d) == 0) { 160 if (Double.compare(0.0D, d) == 0) {
289 return DOUBLE_0; 161 return DOUBLE_0;
290 } 162 }
291 if (Double.compare(d, 1.0D) == 0) { 163 if (Double.compare(d, 1.0D) == 0) {
292 return DOUBLE_1; 164 return DOUBLE_1;
293 } 165 }
294 return new Constant(Kind.Double, null, Double.doubleToRawLongBits(d)); 166 return new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(d));
295 } 167 }
296 168
297 /** 169 /**
298 * Creates a boxed float constant. 170 * Creates a boxed float constant.
299 * 171 *
300 * @param f the float value to box 172 * @param f the float value to box
301 * @return a boxed copy of {@code value} 173 * @return a boxed copy of {@code value}
302 */ 174 */
303 public static Constant forFloat(float f) { 175 public static Constant forFloat(float f) {
304 if (Float.compare(f, 0.0F) == 0) { 176 if (Float.compare(f, 0.0F) == 0) {
308 return FLOAT_1; 180 return FLOAT_1;
309 } 181 }
310 if (Float.compare(f, 2.0F) == 0) { 182 if (Float.compare(f, 2.0F) == 0) {
311 return FLOAT_2; 183 return FLOAT_2;
312 } 184 }
313 return new Constant(Kind.Float, null, Float.floatToRawIntBits(f)); 185 return new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(f));
314 } 186 }
315 187
316 /** 188 /**
317 * Creates a boxed long constant. 189 * Creates a boxed long constant.
318 * 190 *
319 * @param i the long value to box 191 * @param i the long value to box
320 * @return a boxed copy of {@code value} 192 * @return a boxed copy of {@code value}
321 */ 193 */
322 public static Constant forLong(long i) { 194 public static Constant forLong(long i) {
323 return i == 0 ? LONG_0 : i == 1 ? LONG_1 : new Constant(Kind.Long, null, i); 195 return i == 0 ? LONG_0 : i == 1 ? LONG_1 : new PrimitiveConstant(Kind.Long, i);
324 } 196 }
325 197
326 /** 198 /**
327 * Creates a boxed integer constant. 199 * Creates a boxed integer constant.
328 * 200 *
329 * @param i the integer value to box 201 * @param i the integer value to box
330 * @return a boxed copy of {@code value} 202 * @return a boxed copy of {@code value}
331 */ 203 */
332 public static Constant forInt(int i) { 204 public static Constant forInt(int i) {
333 if (i == -1) { 205 if (i == -1) {
334 return INT_MINUS_1; 206 return INT_MINUS_1;
335 } 207 }
336 if (i >= 0 && i < INT_CONSTANT_CACHE.length) { 208 if (i >= 0 && i < INT_CONSTANT_CACHE.length) {
337 return INT_CONSTANT_CACHE[i]; 209 return INT_CONSTANT_CACHE[i];
338 } 210 }
339 return new Constant(Kind.Int, null, i); 211 return new PrimitiveConstant(Kind.Int, i);
340 } 212 }
341 213
342 /** 214 /**
343 * Creates a boxed byte constant. 215 * Creates a boxed byte constant.
344 * 216 *
345 * @param i the byte value to box 217 * @param i the byte value to box
346 * @return a boxed copy of {@code value} 218 * @return a boxed copy of {@code value}
347 */ 219 */
348 public static Constant forByte(byte i) { 220 public static Constant forByte(byte i) {
349 return new Constant(Kind.Byte, null, i); 221 return new PrimitiveConstant(Kind.Byte, i);
350 } 222 }
351 223
352 /** 224 /**
353 * Creates a boxed boolean constant. 225 * Creates a boxed boolean constant.
354 * 226 *
355 * @param i the boolean value to box 227 * @param i the boolean value to box
356 * @return a boxed copy of {@code value} 228 * @return a boxed copy of {@code value}
357 */ 229 */
358 public static Constant forBoolean(boolean i) { 230 public static Constant forBoolean(boolean i) {
359 return i ? TRUE : FALSE; 231 return i ? TRUE : FALSE;
360 } 232 }
361 233
362 /** 234 /**
363 * Creates a boxed char constant. 235 * Creates a boxed char constant.
364 * 236 *
365 * @param i the char value to box 237 * @param i the char value to box
366 * @return a boxed copy of {@code value} 238 * @return a boxed copy of {@code value}
367 */ 239 */
368 public static Constant forChar(char i) { 240 public static Constant forChar(char i) {
369 return new Constant(Kind.Char, null, i); 241 return new PrimitiveConstant(Kind.Char, i);
370 } 242 }
371 243
372 /** 244 /**
373 * Creates a boxed short constant. 245 * Creates a boxed short constant.
374 * 246 *
375 * @param i the short value to box 247 * @param i the short value to box
376 * @return a boxed copy of {@code value} 248 * @return a boxed copy of {@code value}
377 */ 249 */
378 public static Constant forShort(short i) { 250 public static Constant forShort(short i) {
379 return new Constant(Kind.Short, null, i); 251 return new PrimitiveConstant(Kind.Short, i);
380 } 252 }
381 253
382 /** 254 /**
383 * Creates a boxed object constant. 255 * Creates a {@link Constant} from a primitive integer of a certain kind.
384 * 256 */
385 * @param o the object value to box 257 public static Constant forIntegerKind(Kind kind, long i) {
386 * @return a boxed copy of {@code value}
387 */
388 public static Constant forObject(Object o) {
389 if (o == null) {
390 return NULL_OBJECT;
391 }
392 return new Constant(Kind.Object, o, 0L);
393 }
394
395 /**
396 * Creates an annotated int or long constant. An annotation enables a client to associate some
397 * extra semantic or debugging information with a primitive. An annotated primitive constant is
398 * never {@linkplain #equals(Object) equal} to a non-annotated constant.
399 *
400 * @param kind the type of this constant
401 * @param i the value of this constant
402 * @param annotation an arbitrary non-null object
403 */
404 public static Constant forIntegerKind(Kind kind, long i, Object annotation) {
405 switch (kind) { 258 switch (kind) {
406 case Int: 259 case Int:
407 return new Constant(kind, annotation, (int) i); 260 return new PrimitiveConstant(kind, (int) i);
408 case Long: 261 case Long:
409 return new Constant(kind, annotation, i); 262 return new PrimitiveConstant(kind, i);
410 default: 263 default:
411 throw new IllegalArgumentException("not an integer kind: " + kind); 264 throw new IllegalArgumentException("not an integer kind: " + kind);
412 } 265 }
413 } 266 }
414 267
416 * Creates a {@link Constant} from a primitive integer of a certain width. 269 * Creates a {@link Constant} from a primitive integer of a certain width.
417 */ 270 */
418 public static Constant forPrimitiveInt(int bits, long i) { 271 public static Constant forPrimitiveInt(int bits, long i) {
419 assert bits <= 64; 272 assert bits <= 64;
420 if (bits > 32) { 273 if (bits > 32) {
421 return new Constant(Kind.Long, null, i); 274 return new PrimitiveConstant(Kind.Long, i);
422 } else { 275 } else {
423 return new Constant(Kind.Int, null, (int) i); 276 return new PrimitiveConstant(Kind.Int, (int) i);
424 } 277 }
425 } 278 }
426 279
427 /** 280 /**
428 * Creates a boxed constant for the given kind from an Object. The object needs to be of the 281 * Creates a boxed constant for the given boxed primitive value.
429 * Java boxed type corresponding to the kind. 282 *
430 * 283 * @param value the Java boxed value
431 * @param kind the kind of the constant to create 284 * @return the primitive constant holding the {@code value}
432 * @param value the Java boxed value: a {@link Byte} instance for {@link Kind#Byte}, etc. 285 */
433 * @return the boxed copy of {@code value} 286 public static Constant forBoxedPrimitive(Object value) {
434 */ 287 if (value instanceof Boolean) {
435 public static Constant forBoxed(Kind kind, Object value) { 288 return forBoolean((Boolean) value);
436 switch (kind) { 289 } else if (value instanceof Byte) {
437 case Boolean: 290 return forByte((Byte) value);
438 return forBoolean((Boolean) value); 291 } else if (value instanceof Character) {
439 case Byte: 292 return forChar((Character) value);
440 return forByte((Byte) value); 293 } else if (value instanceof Short) {
441 case Char: 294 return forShort((Short) value);
442 return forChar((Character) value); 295 } else if (value instanceof Integer) {
443 case Short: 296 return forInt((Integer) value);
444 return forShort((Short) value); 297 } else if (value instanceof Long) {
445 case Int: 298 return forLong((Long) value);
446 return forInt((Integer) value); 299 } else if (value instanceof Float) {
447 case Long: 300 return forFloat((Float) value);
448 return forLong((Long) value); 301 } else if (value instanceof Double) {
449 case Float: 302 return forDouble((Double) value);
450 return forFloat((Float) value); 303 } else {
451 case Double: 304 return null;
452 return forDouble((Double) value);
453 case Object:
454 return forObject(value);
455 default:
456 throw new RuntimeException("cannot create Constant for boxed " + kind + " value");
457 } 305 }
458 } 306 }
459 307
460 public static Constant forIllegal() { 308 public static Constant forIllegal() {
461 return new Constant(Kind.Illegal, null, 0); 309 return new PrimitiveConstant(Kind.Illegal, 0);
462 } 310 }
463 311
464 /** 312 /**
465 * Returns a constant with the default value for the given kind. 313 * Returns a constant with the default value for the given kind.
466 */ 314 */