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 import java.nio.*;
  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 
  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 
  49     @Override
  50     public JavaKind getJavaKind() {
  51         return kind;
  52     }
  53 
  54     @Override
  55     public boolean isNull() {
  56         return false;
  57     }
  58 
  59     @Override
  60     public boolean isDefaultForKind() {
  61         return primitive == 0;
  62     }
  63 
  64     @Override
  65     public boolean asBoolean() {
  66         assert getJavaKind() == JavaKind.Boolean;
  67         return primitive != 0L;
  68     }
  69 
  70     @Override
  71     public int asInt() {
  72         assert getJavaKind().getStackKind() == JavaKind.Int : getJavaKind().getStackKind();
  73         return (int) primitive;
  74     }
  75 
  76     @Override
  77     public long asLong() {
  78         assert getJavaKind().isNumericInteger();
  79         return primitive;
  80     }
  81 
  82     @Override
  83     public float asFloat() {
  84         assert getJavaKind() == JavaKind.Float;
  85         return Float.intBitsToFloat((int) primitive);
  86     }
  87 
  88     @Override
  89     public double asDouble() {
  90         assert getJavaKind() == JavaKind.Double;
  91         return Double.longBitsToDouble(primitive);
  92     }
  93 
  94     @Override
  95     public Object asBoxedPrimitive() {
  96         switch (getJavaKind()) {
  97             case Byte:
  98                 return Byte.valueOf((byte) primitive);
  99             case Boolean:
 100                 return Boolean.valueOf(asBoolean());
 101             case Short:
 102                 return Short.valueOf((short) primitive);
 103             case Char:
 104                 return Character.valueOf((char) primitive);
 105             case Int:
 106                 return Integer.valueOf(asInt());
 107             case Long:
 108                 return Long.valueOf(asLong());
 109             case Float:
 110                 return Float.valueOf(asFloat());
 111             case Double:
 112                 return Double.valueOf(asDouble());
 113             default:
 114                 throw new IllegalArgumentException("unexpected kind " + getJavaKind());
 115         }
 116     }
 117 
 118     @Override
 119     public int getSerializedSize() {
 120         return getJavaKind().getByteCount();
 121     }
 122 
 123     @Override
 124     public void serialize(ByteBuffer buffer) {
 125         switch (getJavaKind()) {
 126             case Byte:
 127             case Boolean:
 128                 buffer.put((byte) primitive);
 129                 break;
 130             case Short:
 131                 buffer.putShort((short) primitive);
 132                 break;
 133             case Char:
 134                 buffer.putChar((char) primitive);
 135                 break;
 136             case Int:
 137                 buffer.putInt(asInt());
 138                 break;
 139             case Long:
 140                 buffer.putLong(asLong());
 141                 break;
 142             case Float:
 143                 buffer.putFloat(asFloat());
 144                 break;
 145             case Double:
 146                 buffer.putDouble(asDouble());
 147                 break;
 148             default:
 149                 throw new IllegalArgumentException("unexpected kind " + getJavaKind());
 150         }
 151     }
 152 
 153     @Override
 154     public int hashCode() {
 155         return (int) (primitive ^ (primitive >>> 32)) * (getJavaKind().ordinal() + 31);
 156     }
 157 
 158     @Override
 159     public boolean equals(Object o) {
 160         if (o == this) {
 161             return true;
 162         }
 163         if (!(o instanceof PrimitiveConstant)) {
 164             return false;
 165         }
 166         PrimitiveConstant other = (PrimitiveConstant) o;
 167         return this.kind.equals(other.kind) && this.primitive == other.primitive;
 168     }
 169 
 170     @Override
 171     public String toString() {
 172         if (getJavaKind() == JavaKind.Illegal) {
 173             return "illegal";
 174         } else {
 175             return getJavaKind().getJavaName() + "[" + asBoxedPrimitive() + "|0x" + Long.toHexString(primitive) + "]";
 176         }
 177     }
 178 }