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