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     public static JavaConstant forBoxedValue(JavaKind kind, Object value) {
  57         if (kind == JavaKind.Object) {
  58             return HotSpotObjectConstantImpl.forObject(value);
  59         } else {
  60             return JavaConstant.forBoxedPrimitive(value);
  61         }
  62     }
  63 
  64     static Object asBoxedValue(Constant constant) {
  65         if (JavaConstant.isNull(constant)) {
  66             return null;
  67         } else if (constant instanceof HotSpotObjectConstantImpl) {
  68             return ((HotSpotObjectConstantImpl) constant).object;
  69         } else {
  70             return ((JavaConstant) constant).asBoxedPrimitive();
  71         }
  72     }
  73 
  74     private final Object object;
  75     private final boolean compressed;
  76 
  77     private HotSpotObjectConstantImpl(Object object, boolean compressed) {
  78         this.object = object;
  79         this.compressed = compressed;
  80         assert object != null;
  81     }
  82 
  83     @Override
  84     public JavaKind getJavaKind() {
  85         return JavaKind.Object;
  86     }
  87 
  88     /**
  89      * Package-private accessor for the object represented by this constant.
  90      */
  91     Object object() {
  92         return object;
  93     }
  94 
  95     public boolean isCompressed() {
  96         return compressed;
  97     }
  98 
  99     public JavaConstant compress() {
 100         assert !compressed;
 101         return new HotSpotObjectConstantImpl(object, true);
 102     }
 103 
 104     public JavaConstant uncompress() {
 105         assert compressed;
 106         return new HotSpotObjectConstantImpl(object, false);
 107     }
 108 
 109     public HotSpotResolvedObjectType getType() {
 110         return fromObjectClass(object.getClass());
 111     }
 112 
 113     public JavaConstant getClassLoader() {
 114         if (object instanceof Class) {
 115             /*
 116              * This is an intrinsic for getClassLoader0, which occurs after any security checks. We
 117              * can't call that directly so just call getClassLoader.
 118              */
 119             return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getClassLoader());
 120         }
 121         return null;
 122     }
 123 
 124     public int getIdentityHashCode() {
 125         return System.identityHashCode(object);
 126     }
 127 
 128     public JavaConstant getComponentType() {
 129         if (object instanceof Class) {
 130             return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getComponentType());
 131         }
 132         return null;
 133     }
 134 
 135     public JavaConstant getSuperclass() {
 136         if (object instanceof Class) {
 137             return HotSpotObjectConstantImpl.forObject(((Class<?>) object).getSuperclass());
 138         }
 139         return null;
 140     }
 141 
 142     public JavaConstant getCallSiteTarget(Assumptions assumptions) {
 143         if (object instanceof CallSite) {
 144             CallSite callSite = (CallSite) object;
 145             MethodHandle target = callSite.getTarget();
 146             if (!(callSite instanceof ConstantCallSite)) {
 147                 if (assumptions == null) {
 148                     return null;
 149                 }
 150                 assumptions.record(new Assumptions.CallSiteTargetValue(callSite, target));
 151             }
 152             return HotSpotObjectConstantImpl.forObject(target);
 153         }
 154         return null;
 155     }
 156 
 157     @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality is what we want")
 158     public boolean isInternedString() {
 159         if (object instanceof String) {
 160             String s = (String) object;
 161             return s.intern() == s;
 162         }
 163         return false;
 164     }
 165 
 166     public <T> T asObject(Class<T> type) {
 167         if (type.isInstance(object)) {
 168             return type.cast(object);
 169         }
 170         return null;
 171     }
 172 
 173     public Object asObject(ResolvedJavaType type) {
 174         if (type.isInstance(this)) {
 175             return object;
 176         }
 177         return null;
 178     }
 179 
 180     @Override
 181     public boolean isNull() {
 182         return false;
 183     }
 184 
 185     @Override
 186     public boolean isDefaultForKind() {
 187         return false;
 188     }
 189 
 190     @Override
 191     public Object asBoxedPrimitive() {
 192         throw new IllegalArgumentException();
 193     }
 194 
 195     @Override
 196     public int asInt() {
 197         throw new IllegalArgumentException();
 198     }
 199 
 200     @Override
 201     public boolean asBoolean() {
 202         throw new IllegalArgumentException();
 203     }
 204 
 205     @Override
 206     public long asLong() {
 207         throw new IllegalArgumentException();
 208     }
 209 
 210     @Override
 211     public float asFloat() {
 212         throw new IllegalArgumentException();
 213     }
 214 
 215     @Override
 216     public double asDouble() {
 217         throw new IllegalArgumentException();
 218     }
 219 
 220     @Override
 221     public int hashCode() {
 222         return System.identityHashCode(object);
 223     }
 224 
 225     @Override
 226     public boolean equals(Object o) {
 227         if (o == this) {
 228             return true;
 229         } else if (o instanceof HotSpotObjectConstantImpl) {
 230             HotSpotObjectConstantImpl other = (HotSpotObjectConstantImpl) o;
 231             return object == other.object && compressed == other.compressed;
 232         }
 233         return false;
 234     }
 235 
 236     @Override
 237     public String toValueString() {
 238         if (object instanceof String) {
 239             return "\"" + (String) object + "\"";
 240         } else {
 241             return JavaKind.Object.format(object);
 242         }
 243     }
 244 
 245     @Override
 246     public String toString() {
 247         return (compressed ? "NarrowOop" : getJavaKind().getJavaName()) + "[" + JavaKind.Object.format(object) + "]";
 248     }
 249 }