1 /*
   2  * Copyright (c) 2018, 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.hotspot;
  24 
  25 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
  26 
  27 import java.lang.annotation.Annotation;
  28 import java.lang.reflect.Array;
  29 import java.lang.reflect.Type;
  30 
  31 import jdk.vm.ci.meta.JavaConstant;
  32 import jdk.vm.ci.meta.JavaKind;
  33 import jdk.vm.ci.meta.ResolvedJavaMethod;
  34 import jdk.vm.ci.meta.ResolvedJavaType;
  35 
  36 /**
  37  * Implementation of {@link HotSpotJVMCIReflection} when running in a JVMCI shared library.
  38  */
  39 class SharedLibraryJVMCIReflection extends HotSpotJVMCIReflection {
  40 
  41     @Override
  42     Object resolveObject(HotSpotObjectConstantImpl objectHandle) {
  43         throw new HotSpotJVMCIUnsupportedOperationError("cannot resolve handle in a JVMCI shared library to a raw object: " + objectHandle);
  44     }
  45 
  46     @Override
  47     boolean isInstance(HotSpotResolvedObjectTypeImpl holder, HotSpotObjectConstantImpl obj) {
  48         if (obj instanceof DirectHotSpotObjectConstantImpl) {
  49             ResolvedJavaType type = getType(obj);
  50             return holder.isAssignableFrom(type);
  51         }
  52         return runtime().compilerToVm.isInstance(holder, obj);
  53     }
  54 
  55     @Override
  56     boolean isAssignableFrom(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedObjectTypeImpl otherType) {
  57         return runtime().compilerToVm.isAssignableFrom(holder, otherType);
  58     }
  59 
  60     @Override
  61     boolean isLocalClass(HotSpotResolvedObjectTypeImpl holder) {
  62         throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.isLocalClass()");
  63     }
  64 
  65     @Override
  66     boolean isMemberClass(HotSpotResolvedObjectTypeImpl holder) {
  67         throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.isMemberClass()");
  68     }
  69 
  70     @Override
  71     HotSpotResolvedObjectType getEnclosingClass(HotSpotResolvedObjectTypeImpl holder) {
  72         throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.getEnclosingClass()");
  73     }
  74 
  75     @Override
  76     JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedJavaField field, boolean isVolatile) {
  77         JavaConstant javaConstant = runtime().compilerToVm.readFieldValue(holder, field, isVolatile);
  78         if (javaConstant == null) {
  79             return JavaConstant.NULL_POINTER;
  80         }
  81         return javaConstant;
  82     }
  83 
  84     @Override
  85     JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile) {
  86         if (object instanceof DirectHotSpotObjectConstantImpl) {
  87             // cannot read fields from objects due to lack of
  88             // general reflection support in native image
  89             return null;
  90         }
  91         JavaConstant javaConstant = runtime().compilerToVm.readFieldValue(object, field, isVolatile);
  92         if (javaConstant == null) {
  93             return JavaConstant.NULL_POINTER;
  94         }
  95         return javaConstant;
  96     }
  97 
  98     @Override
  99     boolean equals(HotSpotObjectConstantImpl x, HotSpotObjectConstantImpl y) {
 100         if (x == y) {
 101             return true;
 102         }
 103         if (x.compressed != y.compressed) {
 104             return false;
 105         }
 106         if (x instanceof DirectHotSpotObjectConstantImpl && y instanceof DirectHotSpotObjectConstantImpl) {
 107             DirectHotSpotObjectConstantImpl xd = (DirectHotSpotObjectConstantImpl) x;
 108             DirectHotSpotObjectConstantImpl yd = (DirectHotSpotObjectConstantImpl) y;
 109             return (xd.object == yd.object);
 110         }
 111         if (x instanceof DirectHotSpotObjectConstantImpl || y instanceof DirectHotSpotObjectConstantImpl) {
 112             // Mixing of constant types is always inequal
 113             return false;
 114         }
 115         IndirectHotSpotObjectConstantImpl indirectX = (IndirectHotSpotObjectConstantImpl) x;
 116         IndirectHotSpotObjectConstantImpl indirectY = (IndirectHotSpotObjectConstantImpl) y;
 117         return runtime().compilerToVm.equals(x, indirectX.objectHandle, y, indirectY.objectHandle);
 118     }
 119 
 120     @Override
 121     JavaConstant getJavaMirror(HotSpotResolvedPrimitiveType hotSpotResolvedPrimitiveType) {
 122         return runtime().compilerToVm.getJavaMirror(hotSpotResolvedPrimitiveType);
 123     }
 124 
 125     @Override
 126     ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod) {
 127         // ResolvedJavaMethod.getParameters allows a return value of null
 128         return null;
 129     }
 130 
 131     // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
 132     static Annotation[] getClassAnnotations(String className) {
 133         throw new InternalError("missing substitution: " + className);
 134     }
 135 
 136     // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
 137     static Annotation[][] getParameterAnnotations(String className, String methodName) {
 138         throw new InternalError("missing substitution: " + className + " " + methodName);
 139     }
 140 
 141     @Override
 142     Annotation[] getAnnotations(HotSpotResolvedObjectTypeImpl holder) {
 143         return getClassAnnotations(holder.getName());
 144     }
 145 
 146     @Override
 147     Annotation[] getDeclaredAnnotations(HotSpotResolvedObjectTypeImpl holder) {
 148         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 149     }
 150 
 151     @Override
 152     <T extends Annotation> T getAnnotation(HotSpotResolvedObjectTypeImpl holder, Class<T> annotationClass) {
 153         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 154     }
 155 
 156     @Override
 157     Annotation[][] getParameterAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
 158         return getParameterAnnotations(javaMethod.getDeclaringClass().getName(), javaMethod.getName());
 159     }
 160 
 161     @Override
 162     Type[] getGenericParameterTypes(HotSpotResolvedJavaMethodImpl javaMethod) {
 163         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 164     }
 165 
 166     @Override
 167     Annotation[] getFieldAnnotations(HotSpotResolvedJavaFieldImpl javaField) {
 168         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 169     }
 170 
 171     @Override
 172     Annotation[] getMethodAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
 173         return getMethodAnnotationsInternal(javaMethod);
 174     }
 175 
 176     @Override
 177     <T extends Annotation> T getMethodAnnotation(HotSpotResolvedJavaMethodImpl javaMethod, Class<T> annotationClass) {
 178         Annotation[] methodAnnotations = getMethodAnnotations(javaMethod);
 179         if (methodAnnotations != null) {
 180             for (Annotation ann : methodAnnotations) {
 181                 if (annotationClass.isInstance(ann)) {
 182                     return annotationClass.cast(ann);
 183                 }
 184             }
 185         }
 186         return null;
 187     }
 188 
 189     // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
 190     @SuppressWarnings("unused")
 191     private static Annotation[] getMethodAnnotationsInternal(ResolvedJavaMethod javaMethod) {
 192         throw new InternalError("missing substitution");
 193     }
 194 
 195     @Override
 196     Annotation[] getMethodDeclaredAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
 197         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 198     }
 199 
 200     @Override
 201     Annotation[] getFieldDeclaredAnnotations(HotSpotResolvedJavaFieldImpl javaMethod) {
 202         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 203     }
 204 
 205     @Override
 206     <T extends Annotation> T getFieldAnnotation(HotSpotResolvedJavaFieldImpl javaField, Class<T> annotationClass) {
 207         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 208     }
 209 
 210     @Override
 211     HotSpotResolvedObjectTypeImpl getType(HotSpotObjectConstantImpl object) {
 212         if (object instanceof DirectHotSpotObjectConstantImpl) {
 213             Class<?> theClass = ((DirectHotSpotObjectConstantImpl) object).object.getClass();
 214             try {
 215                 String name = theClass.getName().replace('.', '/');
 216                 HotSpotResolvedObjectTypeImpl type = (HotSpotResolvedObjectTypeImpl) runtime().compilerToVm.lookupType(name, null, true);
 217                 if (type == null) {
 218                     throw new InternalError(name);
 219                 }
 220                 return type;
 221             } catch (ClassNotFoundException e) {
 222                 throw new InternalError(e);
 223             }
 224         }
 225         return runtime().compilerToVm.getResolvedJavaType(object, runtime().getConfig().hubOffset, false);
 226     }
 227 
 228     @Override
 229     String asString(HotSpotObjectConstantImpl object) {
 230         if (object instanceof IndirectHotSpotObjectConstantImpl) {
 231             return runtime().compilerToVm.asString(object);
 232         }
 233         Object value = ((DirectHotSpotObjectConstantImpl) object).object;
 234         if (value instanceof String) {
 235             return (String) value;
 236         }
 237         return null;
 238     }
 239 
 240     @Override
 241     ResolvedJavaType asJavaType(HotSpotObjectConstantImpl object) {
 242         if (object instanceof DirectHotSpotObjectConstantImpl) {
 243             DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
 244             if (direct.object instanceof Class) {
 245                 Class<?> javaClass = (Class<?>) direct.object;
 246                 return runtime().fromClass(javaClass);
 247             }
 248             if (direct.object instanceof ResolvedJavaType) {
 249                 return (ResolvedJavaType) convertUnknownValue(direct.object);
 250             }
 251             return null;
 252         }
 253         return runtime().compilerToVm.asJavaType(object);
 254     }
 255 
 256     // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
 257     static Object convertUnknownValue(Object object) {
 258         return object;
 259     }
 260 
 261     @SuppressWarnings("unchecked")
 262     @Override
 263     <T> T asObject(HotSpotObjectConstantImpl object, Class<T> type) {
 264         if (object instanceof DirectHotSpotObjectConstantImpl) {
 265             Object theObject = ((DirectHotSpotObjectConstantImpl) object).object;
 266             if (type.isInstance(theObject)) {
 267                 return (T) convertUnknownValue(type.cast(theObject));
 268             }
 269         }
 270         return null;
 271     }
 272 
 273     @Override
 274     Object asObject(HotSpotObjectConstantImpl object, HotSpotResolvedJavaType type) {
 275         throw new HotSpotJVMCIUnsupportedOperationError("cannot resolve a shared library JVMCI object handle to a " +
 276                         "raw object as it may be in another runtime");
 277     }
 278 
 279     @Override
 280     String formatString(HotSpotObjectConstantImpl object) {
 281         if (object instanceof DirectHotSpotObjectConstantImpl) {
 282             DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
 283             return "CompilerObject<" + direct.object.getClass().getName() + ">";
 284         }
 285         return "Instance<" + object.getType().toJavaName() + ">";
 286     }
 287 
 288     @Override
 289     Integer getLength(HotSpotObjectConstantImpl object) {
 290         if (object instanceof DirectHotSpotObjectConstantImpl) {
 291             DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
 292             if (direct.object.getClass().isArray()) {
 293                 return Array.getLength(direct.object);
 294             }
 295             return null;
 296         }
 297         int length = runtime().compilerToVm.getArrayLength(object);
 298         if (length >= 0) {
 299             return length;
 300         }
 301         return null;
 302     }
 303 
 304     @Override
 305     JavaConstant readArrayElement(HotSpotObjectConstantImpl arrayObject, int index) {
 306         Object result = runtime().compilerToVm.readArrayElement(arrayObject, index);
 307         if (result == null) {
 308             return null;
 309         }
 310         if (result instanceof JavaConstant) {
 311             return (JavaConstant) result;
 312         }
 313         JavaConstant constant = JavaConstant.forBoxedPrimitive(result);
 314         if (constant == null) {
 315             throw new InternalError("Unexpected value " + result);
 316         }
 317         return constant;
 318     }
 319 
 320     @Override
 321     JavaConstant forObject(Object value) {
 322         return DirectHotSpotObjectConstantImpl.forObject(value, false);
 323     }
 324 
 325     @Override
 326     JavaConstant unboxPrimitive(HotSpotObjectConstantImpl source) {
 327         Object box = runtime().compilerToVm.unboxPrimitive(source);
 328         return JavaConstant.forBoxedPrimitive(box);
 329     }
 330 
 331     @Override
 332     JavaConstant boxPrimitive(JavaConstant source) {
 333         return runtime().compilerToVm.boxPrimitive(source.asBoxedPrimitive());
 334     }
 335 
 336     @Override
 337     int getInt(HotSpotObjectConstantImpl object, long displacement) {
 338         return runtime().compilerToVm.getInt(object, displacement);
 339     }
 340 
 341     @Override
 342     byte getByte(HotSpotObjectConstantImpl object, long displacement) {
 343         return runtime().compilerToVm.getByte(object, displacement);
 344     }
 345 
 346     @Override
 347     short getShort(HotSpotObjectConstantImpl object, long displacement) {
 348         return runtime().compilerToVm.getShort(object, displacement);
 349     }
 350 
 351     @Override
 352     long getLong(HotSpotObjectConstantImpl object, long displacement) {
 353         return runtime().compilerToVm.getLong(object, displacement);
 354     }
 355 
 356     @Override
 357     void checkRead(HotSpotObjectConstantImpl constant, JavaKind kind, long displacement, HotSpotResolvedObjectType type) {
 358 
 359     }
 360 }