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      */
getJavaKind()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      */
isNull()60     boolean isNull();
61 
isNull(Constant c)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      */
isNonNull()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     @Override
isDefaultForKind()85     boolean isDefaultForKind();
86 
87     /**
88      * Returns the value of this constant as a boxed Java value.
89      *
90      * @return the value of this constant
91      */
asBoxedPrimitive()92     Object asBoxedPrimitive();
93 
94     /**
95      * Returns the primitive int value this constant represents. The constant must have a
96      * {@link JavaKind#getStackKind()} of {@link JavaKind#Int}.
97      *
98      * @return the constant value
99      */
asInt()100     int asInt();
101 
102     /**
103      * Returns the primitive boolean value this constant represents. The constant must have kind
104      * {@link JavaKind#Boolean}.
105      *
106      * @return the constant value
107      */
asBoolean()108     boolean asBoolean();
109 
110     /**
111      * Returns the primitive long value this constant represents. The constant must have kind
112      * {@link JavaKind#Long}, a {@link JavaKind#getStackKind()} of {@link JavaKind#Int}.
113      *
114      * @return the constant value
115      */
asLong()116     long asLong();
117 
118     /**
119      * Returns the primitive float value this constant represents. The constant must have kind
120      * {@link JavaKind#Float}.
121      *
122      * @return the constant value
123      */
asFloat()124     float asFloat();
125 
126     /**
127      * Returns the primitive double value this constant represents. The constant must have kind
128      * {@link JavaKind#Double}.
129      *
130      * @return the constant value
131      */
asDouble()132     double asDouble();
133 
134     @Override
toValueString()135     default String toValueString() {
136         if (getJavaKind() == JavaKind.Illegal) {
137             return "illegal";
138         } else {
139             return getJavaKind().format(asBoxedPrimitive());
140         }
141     }
142 
toString(JavaConstant constant)143     static String toString(JavaConstant constant) {
144         if (constant.getJavaKind() == JavaKind.Illegal) {
145             return "illegal";
146         } else {
147             return constant.getJavaKind().getJavaName() + "[" + constant.toValueString() + "]";
148         }
149     }
150 
151     /**
152      * Creates a boxed double constant.
153      *
154      * @param d the double value to box
155      * @return a boxed copy of {@code value}
156      */
forDouble(double d)157     static PrimitiveConstant forDouble(double d) {
158         if (Double.compare(0.0D, d) == 0) {
159             return DOUBLE_0;
160         }
161         if (Double.compare(d, 1.0D) == 0) {
162             return DOUBLE_1;
163         }
164         return new PrimitiveConstant(JavaKind.Double, Double.doubleToRawLongBits(d));
165     }
166 
167     /**
168      * Creates a boxed float constant.
169      *
170      * @param f the float value to box
171      * @return a boxed copy of {@code value}
172      */
forFloat(float f)173     static PrimitiveConstant forFloat(float f) {
174         if (Float.compare(f, 0.0F) == 0) {
175             return FLOAT_0;
176         }
177         if (Float.compare(f, 1.0F) == 0) {
178             return FLOAT_1;
179         }
180         return new PrimitiveConstant(JavaKind.Float, Float.floatToRawIntBits(f));
181     }
182 
183     /**
184      * Creates a boxed long constant.
185      *
186      * @param i the long value to box
187      * @return a boxed copy of {@code value}
188      */
forLong(long i)189     static PrimitiveConstant forLong(long i) {
190         if (i == 0) {
191             return LONG_0;
192         } else if (i == 1) {
193             return LONG_1;
194         } else {
195             return new PrimitiveConstant(JavaKind.Long, i);
196         }
197     }
198 
199     /**
200      * Creates a boxed integer constant.
201      *
202      * @param i the integer value to box
203      * @return a boxed copy of {@code value}
204      */
forInt(int i)205     static PrimitiveConstant forInt(int i) {
206         switch (i) {
207             case -1:
208                 return INT_MINUS_1;
209             case 0:
210                 return INT_0;
211             case 1:
212                 return INT_1;
213             case 2:
214                 return INT_2;
215             default:
216                 return new PrimitiveConstant(JavaKind.Int, i);
217         }
218     }
219 
220     /**
221      * Creates a boxed byte constant.
222      *
223      * @param i the byte value to box
224      * @return a boxed copy of {@code value}
225      */
forByte(byte i)226     static PrimitiveConstant forByte(byte i) {
227         return new PrimitiveConstant(JavaKind.Byte, i);
228     }
229 
230     /**
231      * Creates a boxed boolean constant.
232      *
233      * @param i the boolean value to box
234      * @return a boxed copy of {@code value}
235      */
forBoolean(boolean i)236     static PrimitiveConstant forBoolean(boolean i) {
237         return i ? TRUE : FALSE;
238     }
239 
240     /**
241      * Creates a boxed char constant.
242      *
243      * @param i the char value to box
244      * @return a boxed copy of {@code value}
245      */
forChar(char i)246     static PrimitiveConstant forChar(char i) {
247         return new PrimitiveConstant(JavaKind.Char, i);
248     }
249 
250     /**
251      * Creates a boxed short constant.
252      *
253      * @param i the short value to box
254      * @return a boxed copy of {@code value}
255      */
forShort(short i)256     static PrimitiveConstant forShort(short i) {
257         return new PrimitiveConstant(JavaKind.Short, i);
258     }
259 
260     /**
261      * Creates a {@link JavaConstant} from a primitive integer of a certain kind.
262      */
forIntegerKind(JavaKind kind, long i)263     static PrimitiveConstant forIntegerKind(JavaKind kind, long i) {
264         switch (kind) {
265             case Boolean:
266                 return forBoolean(i != 0);
267             case Byte:
268                 return forByte((byte) i);
269             case Short:
270                 return forShort((short) i);
271             case Char:
272                 return forChar((char) i);
273             case Int:
274                 return forInt((int) i);
275             case Long:
276                 return forLong(i);
277             default:
278                 throw new IllegalArgumentException("not an integer kind: " + kind);
279         }
280     }
281 
282     /**
283      * Creates a {@link JavaConstant} from a primitive integer of a certain width.
284      */
forPrimitiveInt(int bits, long i)285     static PrimitiveConstant forPrimitiveInt(int bits, long i) {
286         assert bits <= 64;
287         switch (bits) {
288             case 1:
289                 return forBoolean(i != 0);
290             case 8:
291                 return forByte((byte) i);
292             case 16:
293                 return forShort((short) i);
294             case 32:
295                 return forInt((int) i);
296             case 64:
297                 return forLong(i);
298             default:
299                 throw new IllegalArgumentException("unsupported integer width: " + bits);
300         }
301     }
302 
303     /**
304      * Creates a boxed constant for the given boxed primitive value.
305      *
306      * @param value the Java boxed value
307      * @return the primitive constant holding the {@code value}
308      */
forBoxedPrimitive(Object value)309     static PrimitiveConstant forBoxedPrimitive(Object value) {
310         if (value instanceof Boolean) {
311             return forBoolean((Boolean) value);
312         } else if (value instanceof Byte) {
313             return forByte((Byte) value);
314         } else if (value instanceof Character) {
315             return forChar((Character) value);
316         } else if (value instanceof Short) {
317             return forShort((Short) value);
318         } else if (value instanceof Integer) {
319             return forInt((Integer) value);
320         } else if (value instanceof Long) {
321             return forLong((Long) value);
322         } else if (value instanceof Float) {
323             return forFloat((Float) value);
324         } else if (value instanceof Double) {
325             return forDouble((Double) value);
326         } else {
327             return null;
328         }
329     }
330 
forIllegal()331     static PrimitiveConstant forIllegal() {
332         return new PrimitiveConstant(JavaKind.Illegal, 0);
333     }
334 
335     /**
336      * Returns a constant with the default value for the given kind.
337      */
defaultForKind(JavaKind kind)338     static JavaConstant defaultForKind(JavaKind kind) {
339         switch (kind) {
340             case Boolean:
341                 return FALSE;
342             case Byte:
343                 return forByte((byte) 0);
344             case Char:
345                 return forChar((char) 0);
346             case Short:
347                 return forShort((short) 0);
348             case Int:
349                 return INT_0;
350             case Double:
351                 return DOUBLE_0;
352             case Float:
353                 return FLOAT_0;
354             case Long:
355                 return LONG_0;
356             case Object:
357                 return NULL_POINTER;
358             default:
359                 throw new IllegalArgumentException(kind.toString());
360         }
361     }
362 }
363