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.hotspot;
  24 
  25 import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass;
  26 
  27 import java.lang.invoke.CallSite;
  28 import java.lang.invoke.ConstantCallSite;
  29 import java.lang.invoke.MethodHandle;
  30 
  31 import jdk.vm.ci.inittimer.SuppressFBWarnings;
  32 import jdk.vm.ci.meta.Assumptions;
  33 import jdk.vm.ci.meta.Constant;
  34 import jdk.vm.ci.meta.JavaConstant;
  35 import jdk.vm.ci.meta.JavaKind;
  36 import jdk.vm.ci.meta.ResolvedJavaType;
  37 
  38 /**
  39  * Represents a constant non-{@code null} object reference, within the compiler and across the
  40  * compiler/runtime interface.
  41  */
  42 final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, HotSpotProxified {
  43 
  44     static JavaConstant forObject(Object object) {
  45         return forObject(object, false);
  46     }
  47 
  48     static JavaConstant forObject(Object object, boolean compressed) {
  49         if (object == null) {
  50             return compressed ? HotSpotCompressedNullConstant.COMPRESSED_NULL : JavaConstant.NULL_POINTER;
  51         } else {
  52             return new HotSpotObjectConstantImpl(object, compressed);
  53         }
  54     }
  55 
  56     static JavaConstant forStableArray(Object object, int stableDimension, boolean isDefaultStable) {
  57         if (object == null) {
  58             return JavaConstant.NULL_POINTER;
  59         } else {
  60             assert object.getClass().isArray();
  61             return new HotSpotObjectConstantImpl(object, false, stableDimension, isDefaultStable);
  62         }
  63     }
  64 
  65     public static JavaConstant forBoxedValue(JavaKind kind, Object value) {
  66         if (kind == JavaKind.Object) {
  67             return HotSpotObjectConstantImpl.forObject(value);
  68         } else {
  69             return JavaConstant.forBoxedPrimitive(value);
  70         }
  71     }
  72 
  73     static Object asBoxedValue(Constant constant) {
  74         if (JavaConstant.isNull(constant)) {
  75             return null;
  76         } else if (constant instanceof HotSpotObjectConstantImpl) {
  77             return ((HotSpotObjectConstantImpl) constant).object;
  78         } else {
  79             return ((JavaConstant) constant).asBoxedPrimitive();
  80         }
  81     }
  82 
  83     private final Object object;
  84     private final boolean compressed;
  85     private final byte stableDimension;
  86     private final boolean isDefaultStable;
  87 
  88     private HotSpotObjectConstantImpl(Object object, boolean compressed, int stableDimension, boolean isDefaultStable) {
  89         this.object = object;
  90         this.compressed = compressed;
  91         this.stableDimension = (byte) stableDimension;
  92         this.isDefaultStable = isDefaultStable;
  93         assert object != null;
  94         assert stableDimension == 0 || (object != null && object.getClass().isArray());
  95         assert stableDimension >= 0 && stableDimension <= 255;
  96         assert !isDefaultStable || stableDimension > 0;
  97     }
  98 
  99     private HotSpotObjectConstantImpl(Object object, boolean compressed) {
 100         this(object, compressed, 0, false);
 101     }
 102 
 103     @Override
 104     public JavaKind getJavaKind() {
 105         return JavaKind.Object;
 106     }
 107 
 108     /**
 109      * Package-private accessor for the object represented by this constant.
 110      */
 111     Object object() {
 112         return object;
 113     }
 114 
 115     public boolean isCompressed() {
 116         return compressed;
 117     }
 118 
 119     public JavaConstant compress() {
 120         assert !compressed;
 121         return new HotSpotObjectConstantImpl(object, true, stableDimension, isDefaultStable);
 122     }
 123 
 124     public JavaConstant uncompress() {
 125         assert compressed;
 126         return new HotSpotObjectConstantImpl(object, false, stableDimension, isDefaultStable);
 127     }
 128 
 129     public HotSpotResolvedObjectType getType() {
 130         return fromObjectClass(object.getClass());
 131     }
 132 
 133     public JavaConstant getClassLoader() {
 134         if (object instanceof Class) {
 135             /*
 136              * This is an intrinsic for getClassLoader0, which occurs after any security checks. We
 137              * can't call that directly so just call getClassLoader.
 138              */
 139             return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getClassLoader());
 140         }
 141         return null;
 142     }
 143 
 144     public int getIdentityHashCode() {
 145         return System.identityHashCode(object);
 146     }
 147 
 148     public JavaConstant getComponentType() {
 149         if (object instanceof Class) {
 150             return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getComponentType());
 151         }
 152         return null;
 153     }
 154 
 155     public JavaConstant getSuperclass() {
 156         if (object instanceof Class) {
 157             return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getSuperclass());
 158         }
 159         return null;
 160     }
 161 
 162     public JavaConstant getCallSiteTarget(Assumptions assumptions) {
 163         if (object instanceof CallSite) {
 164             CallSite callSite = (CallSite) object;
 165             MethodHandle target = callSite.getTarget();
 166             if (!(callSite instanceof ConstantCallSite)) {
 167                 if (assumptions == null) {
 168                     return null;
 169                 }
 170                 assumptions.record(new Assumptions.CallSiteTargetValue(callSite, target));
 171             }
 172             return HotSpotObjectConstantImpl.forObject(target);
 173         }
 174         return null;
 175     }
 176 
 177     @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality is what we want")
 178     public boolean isInternedString() {
 179         if (object instanceof String) {
 180             String s = (String) object;
 181             return s.intern() == s;
 182         }
 183         return false;
 184     }
 185 
 186     public <T> T asObject(Class<T> type) {
 187         if (type.isInstance(object)) {
 188             return type.cast(object);
 189         }
 190         return null;
 191     }
 192 
 193     public Object asObject(ResolvedJavaType type) {
 194         if (type.isInstance(this)) {
 195             return object;
 196         }
 197         return null;
 198     }
 199 
 200     @Override
 201     public boolean isNull() {
 202         return false;
 203     }
 204 
 205     @Override
 206     public boolean isDefaultForKind() {
 207         return false;
 208     }
 209 
 210     @Override
 211     public Object asBoxedPrimitive() {
 212         throw new IllegalArgumentException();
 213     }
 214 
 215     @Override
 216     public int asInt() {
 217         throw new IllegalArgumentException();
 218     }
 219 
 220     @Override
 221     public boolean asBoolean() {
 222         throw new IllegalArgumentException();
 223     }
 224 
 225     @Override
 226     public long asLong() {
 227         throw new IllegalArgumentException();
 228     }
 229 
 230     @Override
 231     public float asFloat() {
 232         throw new IllegalArgumentException();
 233     }
 234 
 235     @Override
 236     public double asDouble() {
 237         throw new IllegalArgumentException();
 238     }
 239 
 240     @Override
 241     public int hashCode() {
 242         return System.identityHashCode(object);
 243     }
 244 
 245     @Override
 246     public boolean equals(Object o) {
 247         if (o == this) {
 248             return true;
 249         } else if (o instanceof HotSpotObjectConstantImpl) {
 250             HotSpotObjectConstantImpl other = (HotSpotObjectConstantImpl) o;
 251             return object == other.object && compressed == other.compressed && stableDimension == other.stableDimension && isDefaultStable == other.isDefaultStable;
 252         }
 253         return false;
 254     }
 255 
 256     @Override
 257     public String toValueString() {
 258         if (object instanceof String) {
 259             return "\"" + (String) object + "\"";
 260         } else {
 261             return JavaKind.Object.format(object);
 262         }
 263     }
 264 
 265     @Override
 266     public String toString() {
 267         return (compressed ? "NarrowOop" : getJavaKind().getJavaName()) + "[" + JavaKind.Object.format(object) + "]";
 268     }
 269 
 270     /**
 271      * Number of stable dimensions if this constant is a stable array.
 272      */
 273     public int getStableDimension() {
 274         return stableDimension & 0xff;
 275     }
 276 
 277     /**
 278      * Returns {@code true} if this is a stable array constant and its elements should be considered
 279      * as stable regardless of whether they are default values.
 280      */
 281     public boolean isDefaultStable() {
 282         return isDefaultStable;
 283     }
 284 }