001/*
002 * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package jdk.internal.jvmci.meta;
024
025/**
026 * Represents a constant (boxed) value, such as an integer, floating point number, or object
027 * reference, within the compiler and across the compiler/runtime interface. Exports a set of
028 * {@code JavaConstant} instances that represent frequently used constant values, such as
029 * {@link #NULL_POINTER}.
030 */
031public interface JavaConstant extends Constant, JavaValue, Value {
032
033    /*
034     * Using a larger cache for integers leads to only a slight increase in cache hit ratio which is
035     * not enough to justify the impact on startup time.
036     */
037    JavaConstant NULL_POINTER = new NullConstant();
038    PrimitiveConstant INT_MINUS_1 = new PrimitiveConstant(Kind.Int, -1);
039    PrimitiveConstant INT_0 = new PrimitiveConstant(Kind.Int, 0);
040    PrimitiveConstant INT_1 = new PrimitiveConstant(Kind.Int, 1);
041    PrimitiveConstant INT_2 = new PrimitiveConstant(Kind.Int, 2);
042    PrimitiveConstant LONG_0 = new PrimitiveConstant(Kind.Long, 0L);
043    PrimitiveConstant LONG_1 = new PrimitiveConstant(Kind.Long, 1L);
044    PrimitiveConstant FLOAT_0 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(0.0F));
045    PrimitiveConstant FLOAT_1 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(1.0F));
046    PrimitiveConstant DOUBLE_0 = new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(0.0D));
047    PrimitiveConstant DOUBLE_1 = new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(1.0D));
048    PrimitiveConstant TRUE = new PrimitiveConstant(Kind.Boolean, 1L);
049    PrimitiveConstant FALSE = new PrimitiveConstant(Kind.Boolean, 0L);
050
051    /**
052     * Checks whether this constant is null.
053     *
054     * @return {@code true} if this constant is the null constant
055     */
056    boolean isNull();
057
058    static boolean isNull(Constant c) {
059        if (c instanceof JavaConstant) {
060            return ((JavaConstant) c).isNull();
061        } else {
062            return false;
063        }
064    }
065
066    /**
067     * Checks whether this constant is non-null.
068     *
069     * @return {@code true} if this constant is a primitive, or an object constant that is not null
070     */
071    default boolean isNonNull() {
072        return !isNull();
073    }
074
075    /**
076     * Checks whether this constant is the default value for its kind (null, 0, 0.0, false).
077     *
078     * @return {@code true} if this constant is the default value for its kind
079     */
080    boolean isDefaultForKind();
081
082    /**
083     * Returns the value of this constant as a boxed Java value.
084     *
085     * @return the value of this constant
086     */
087    Object asBoxedPrimitive();
088
089    /**
090     * Returns the primitive int value this constant represents. The constant must have a
091     * {@link Kind#getStackKind()} of {@link Kind#Int}.
092     *
093     * @return the constant value
094     */
095    int asInt();
096
097    /**
098     * Returns the primitive boolean value this constant represents. The constant must have kind
099     * {@link Kind#Boolean}.
100     *
101     * @return the constant value
102     */
103    boolean asBoolean();
104
105    /**
106     * Returns the primitive long value this constant represents. The constant must have kind
107     * {@link Kind#Long}, a {@link Kind#getStackKind()} of {@link Kind#Int}.
108     *
109     * @return the constant value
110     */
111    long asLong();
112
113    /**
114     * Returns the primitive float value this constant represents. The constant must have kind
115     * {@link Kind#Float}.
116     *
117     * @return the constant value
118     */
119    float asFloat();
120
121    /**
122     * Returns the primitive double value this constant represents. The constant must have kind
123     * {@link Kind#Double}.
124     *
125     * @return the constant value
126     */
127    double asDouble();
128
129    default String toValueString() {
130        if (getKind() == Kind.Illegal) {
131            return "illegal";
132        } else {
133            return getKind().format(asBoxedPrimitive());
134        }
135    }
136
137    static String toString(JavaConstant constant) {
138        if (constant.getKind() == Kind.Illegal) {
139            return "illegal";
140        } else {
141            return constant.getKind().getJavaName() + "[" + constant.toValueString() + "]";
142        }
143    }
144
145    /**
146     * Creates a boxed double constant.
147     *
148     * @param d the double value to box
149     * @return a boxed copy of {@code value}
150     */
151    static PrimitiveConstant forDouble(double d) {
152        if (Double.compare(0.0D, d) == 0) {
153            return DOUBLE_0;
154        }
155        if (Double.compare(d, 1.0D) == 0) {
156            return DOUBLE_1;
157        }
158        return new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(d));
159    }
160
161    /**
162     * Creates a boxed float constant.
163     *
164     * @param f the float value to box
165     * @return a boxed copy of {@code value}
166     */
167    static PrimitiveConstant forFloat(float f) {
168        if (Float.compare(f, 0.0F) == 0) {
169            return FLOAT_0;
170        }
171        if (Float.compare(f, 1.0F) == 0) {
172            return FLOAT_1;
173        }
174        return new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(f));
175    }
176
177    /**
178     * Creates a boxed long constant.
179     *
180     * @param i the long value to box
181     * @return a boxed copy of {@code value}
182     */
183    static PrimitiveConstant forLong(long i) {
184        if (i == 0) {
185            return LONG_0;
186        } else if (i == 1) {
187            return LONG_1;
188        } else {
189            return new PrimitiveConstant(Kind.Long, i);
190        }
191    }
192
193    /**
194     * Creates a boxed integer constant.
195     *
196     * @param i the integer value to box
197     * @return a boxed copy of {@code value}
198     */
199    static PrimitiveConstant forInt(int i) {
200        switch (i) {
201            case -1:
202                return INT_MINUS_1;
203            case 0:
204                return INT_0;
205            case 1:
206                return INT_1;
207            case 2:
208                return INT_2;
209            default:
210                return new PrimitiveConstant(Kind.Int, i);
211        }
212    }
213
214    /**
215     * Creates a boxed byte constant.
216     *
217     * @param i the byte value to box
218     * @return a boxed copy of {@code value}
219     */
220    static PrimitiveConstant forByte(byte i) {
221        return new PrimitiveConstant(Kind.Byte, i);
222    }
223
224    /**
225     * Creates a boxed boolean constant.
226     *
227     * @param i the boolean value to box
228     * @return a boxed copy of {@code value}
229     */
230    static PrimitiveConstant forBoolean(boolean i) {
231        return i ? TRUE : FALSE;
232    }
233
234    /**
235     * Creates a boxed char constant.
236     *
237     * @param i the char value to box
238     * @return a boxed copy of {@code value}
239     */
240    static PrimitiveConstant forChar(char i) {
241        return new PrimitiveConstant(Kind.Char, i);
242    }
243
244    /**
245     * Creates a boxed short constant.
246     *
247     * @param i the short value to box
248     * @return a boxed copy of {@code value}
249     */
250    static PrimitiveConstant forShort(short i) {
251        return new PrimitiveConstant(Kind.Short, i);
252    }
253
254    /**
255     * Creates a {@link JavaConstant} from a primitive integer of a certain kind.
256     */
257    static PrimitiveConstant forIntegerKind(Kind kind, long i) {
258        switch (kind) {
259            case Boolean:
260                return forBoolean(i != 0);
261            case Byte:
262                return forByte((byte) i);
263            case Short:
264                return forShort((short) i);
265            case Char:
266                return forChar((char) i);
267            case Int:
268                return forInt((int) i);
269            case Long:
270                return forLong(i);
271            default:
272                throw new IllegalArgumentException("not an integer kind: " + kind);
273        }
274    }
275
276    /**
277     * Creates a {@link JavaConstant} from a primitive integer of a certain width.
278     */
279    static PrimitiveConstant forPrimitiveInt(int bits, long i) {
280        assert bits <= 64;
281        switch (bits) {
282            case 1:
283                return forBoolean(i != 0);
284            case 8:
285                return forByte((byte) i);
286            case 16:
287                return forShort((short) i);
288            case 32:
289                return forInt((int) i);
290            case 64:
291                return forLong(i);
292            default:
293                throw new IllegalArgumentException("unsupported integer width: " + bits);
294        }
295    }
296
297    /**
298     * Creates a boxed constant for the given boxed primitive value.
299     *
300     * @param value the Java boxed value
301     * @return the primitive constant holding the {@code value}
302     */
303    static PrimitiveConstant forBoxedPrimitive(Object value) {
304        if (value instanceof Boolean) {
305            return forBoolean((Boolean) value);
306        } else if (value instanceof Byte) {
307            return forByte((Byte) value);
308        } else if (value instanceof Character) {
309            return forChar((Character) value);
310        } else if (value instanceof Short) {
311            return forShort((Short) value);
312        } else if (value instanceof Integer) {
313            return forInt((Integer) value);
314        } else if (value instanceof Long) {
315            return forLong((Long) value);
316        } else if (value instanceof Float) {
317            return forFloat((Float) value);
318        } else if (value instanceof Double) {
319            return forDouble((Double) value);
320        } else {
321            return null;
322        }
323    }
324
325    static PrimitiveConstant forIllegal() {
326        return new PrimitiveConstant(Kind.Illegal, 0);
327    }
328
329    /**
330     * Returns a constant with the default value for the given kind.
331     */
332    static JavaConstant defaultForKind(Kind kind) {
333        switch (kind) {
334            case Boolean:
335                return FALSE;
336            case Byte:
337                return forByte((byte) 0);
338            case Char:
339                return forChar((char) 0);
340            case Short:
341                return forShort((short) 0);
342            case Int:
343                return INT_0;
344            case Double:
345                return DOUBLE_0;
346            case Float:
347                return FLOAT_0;
348            case Long:
349                return LONG_0;
350            case Object:
351                return NULL_POINTER;
352            default:
353                throw new IllegalArgumentException(kind.toString());
354        }
355    }
356
357    /**
358     * Returns the zero value for a given numeric kind.
359     */
360    static JavaConstant zero(Kind kind) {
361        switch (kind) {
362            case Boolean:
363                return FALSE;
364            case Byte:
365                return forByte((byte) 0);
366            case Char:
367                return forChar((char) 0);
368            case Double:
369                return DOUBLE_0;
370            case Float:
371                return FLOAT_0;
372            case Int:
373                return INT_0;
374            case Long:
375                return LONG_0;
376            case Short:
377                return forShort((short) 0);
378            default:
379                throw new IllegalArgumentException(kind.toString());
380        }
381    }
382
383    /**
384     * Returns the one value for a given numeric kind.
385     */
386    static JavaConstant one(Kind kind) {
387        switch (kind) {
388            case Boolean:
389                return TRUE;
390            case Byte:
391                return forByte((byte) 1);
392            case Char:
393                return forChar((char) 1);
394            case Double:
395                return DOUBLE_1;
396            case Float:
397                return FLOAT_1;
398            case Int:
399                return INT_1;
400            case Long:
401                return LONG_1;
402            case Short:
403                return forShort((short) 1);
404            default:
405                throw new IllegalArgumentException(kind.toString());
406        }
407    }
408
409    /**
410     * Adds two numeric constants.
411     */
412    static JavaConstant add(JavaConstant x, JavaConstant y) {
413        assert x.getKind() == y.getKind();
414        switch (x.getKind()) {
415            case Byte:
416                return forByte((byte) (x.asInt() + y.asInt()));
417            case Char:
418                return forChar((char) (x.asInt() + y.asInt()));
419            case Double:
420                return forDouble(x.asDouble() + y.asDouble());
421            case Float:
422                return forFloat(x.asFloat() + y.asFloat());
423            case Int:
424                return forInt(x.asInt() + y.asInt());
425            case Long:
426                return forLong(x.asLong() + y.asLong());
427            case Short:
428                return forShort((short) (x.asInt() + y.asInt()));
429            default:
430                throw new IllegalArgumentException(x.getKind().toString());
431        }
432    }
433
434    /**
435     * Multiplies two numeric constants.
436     */
437    static PrimitiveConstant mul(JavaConstant x, JavaConstant y) {
438        assert x.getKind() == y.getKind();
439        switch (x.getKind()) {
440            case Byte:
441                return forByte((byte) (x.asInt() * y.asInt()));
442            case Char:
443                return forChar((char) (x.asInt() * y.asInt()));
444            case Double:
445                return forDouble(x.asDouble() * y.asDouble());
446            case Float:
447                return forFloat(x.asFloat() * y.asFloat());
448            case Int:
449                return forInt(x.asInt() * y.asInt());
450            case Long:
451                return forLong(x.asLong() * y.asLong());
452            case Short:
453                return forShort((short) (x.asInt() * y.asInt()));
454            default:
455                throw new IllegalArgumentException(x.getKind().toString());
456        }
457    }
458}