1 /*
2  * Copyright (c) 2009, 2019, 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 import java.nio.ByteBuffer;
26 
27 /**
28  * Represents a primitive constant value, such as an integer or floating point number, within the
29  * compiler and across the compiler/runtime interface.
30  */
31 public class PrimitiveConstant implements JavaConstant, SerializableConstant {
32 
33     private final JavaKind kind;
34 
35     /**
36      * The boxed primitive value as a {@code long}. For {@code float} and {@code double} values,
37      * this value is the result of {@link Float#floatToRawIntBits(float)} and
38      * {@link Double#doubleToRawLongBits(double)} respectively.
39      */
40     private final long primitive;
41 
PrimitiveConstant(JavaKind kind, long primitive)42     protected PrimitiveConstant(JavaKind kind, long primitive) {
43         this.primitive = primitive;
44         this.kind = kind;
45 
46         assert kind.isPrimitive() || kind == JavaKind.Illegal;
47     }
48 
forTypeChar(char kind, long i)49     static PrimitiveConstant forTypeChar(char kind, long i) {
50         return JavaConstant.forIntegerKind(JavaKind.fromPrimitiveOrVoidTypeChar(kind), i);
51     }
52 
53     @Override
getJavaKind()54     public JavaKind getJavaKind() {
55         return kind;
56     }
57 
58     @Override
isNull()59     public boolean isNull() {
60         return false;
61     }
62 
63     @Override
isDefaultForKind()64     public boolean isDefaultForKind() {
65         return primitive == 0;
66     }
67 
68     @Override
asBoolean()69     public boolean asBoolean() {
70         assert getJavaKind() == JavaKind.Boolean;
71         return primitive != 0L;
72     }
73 
74     @Override
asInt()75     public int asInt() {
76         assert getJavaKind().getStackKind() == JavaKind.Int : getJavaKind().getStackKind();
77         return (int) primitive;
78     }
79 
80     @Override
asLong()81     public long asLong() {
82         assert getJavaKind().isNumericInteger();
83         return primitive;
84     }
85 
86     @Override
asFloat()87     public float asFloat() {
88         assert getJavaKind() == JavaKind.Float;
89         return Float.intBitsToFloat((int) primitive);
90     }
91 
92     @Override
asDouble()93     public double asDouble() {
94         assert getJavaKind() == JavaKind.Double;
95         return Double.longBitsToDouble(primitive);
96     }
97 
98     @Override
asBoxedPrimitive()99     public Object asBoxedPrimitive() {
100         switch (getJavaKind()) {
101             case Byte:
102                 return Byte.valueOf((byte) primitive);
103             case Boolean:
104                 return Boolean.valueOf(asBoolean());
105             case Short:
106                 return Short.valueOf((short) primitive);
107             case Char:
108                 return Character.valueOf((char) primitive);
109             case Int:
110                 return Integer.valueOf(asInt());
111             case Long:
112                 return Long.valueOf(asLong());
113             case Float:
114                 return Float.valueOf(asFloat());
115             case Double:
116                 return Double.valueOf(asDouble());
117             default:
118                 throw new IllegalArgumentException("unexpected kind " + getJavaKind());
119         }
120     }
121 
122     @Override
getSerializedSize()123     public int getSerializedSize() {
124         return getJavaKind().getByteCount();
125     }
126 
127     @Override
serialize(ByteBuffer buffer)128     public void serialize(ByteBuffer buffer) {
129         switch (getJavaKind()) {
130             case Byte:
131             case Boolean:
132                 buffer.put((byte) primitive);
133                 break;
134             case Short:
135                 buffer.putShort((short) primitive);
136                 break;
137             case Char:
138                 buffer.putChar((char) primitive);
139                 break;
140             case Int:
141                 buffer.putInt(asInt());
142                 break;
143             case Long:
144                 buffer.putLong(asLong());
145                 break;
146             case Float:
147                 buffer.putFloat(asFloat());
148                 break;
149             case Double:
150                 buffer.putDouble(asDouble());
151                 break;
152             default:
153                 throw new IllegalArgumentException("unexpected kind " + getJavaKind());
154         }
155     }
156 
157     @Override
hashCode()158     public int hashCode() {
159         return (int) (primitive ^ (primitive >>> 32)) * (getJavaKind().ordinal() + 31);
160     }
161 
162     @Override
equals(Object o)163     public boolean equals(Object o) {
164         if (o == this) {
165             return true;
166         }
167         if (!(o instanceof PrimitiveConstant)) {
168             return false;
169         }
170         PrimitiveConstant other = (PrimitiveConstant) o;
171         return this.kind.equals(other.kind) && this.primitive == other.primitive;
172     }
173 
174     @Override
toString()175     public String toString() {
176         if (getJavaKind() == JavaKind.Illegal) {
177             return "illegal";
178         } else {
179             return getJavaKind().getJavaName() + "[" + asBoxedPrimitive() + "|0x" + Long.toHexString(primitive) + "]";
180         }
181     }
182 }
183