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         Annotation[] annotations = getClassAnnotations(holder.getName());
 144         return annotations == null ? new Annotation[0] : annotations;
 145     }
 146 
 147     @Override
 148     Annotation[] getDeclaredAnnotations(HotSpotResolvedObjectTypeImpl holder) {
 149         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 150     }
 151 
 152     @Override
 153     <T extends Annotation> T getAnnotation(HotSpotResolvedObjectTypeImpl holder, Class<T> annotationClass) {
 154         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 155     }
 156 
 157     @Override
 158     Annotation[][] getParameterAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
 159         Annotation[][] annotations = getParameterAnnotations(javaMethod.getDeclaringClass().getName(), javaMethod.getName());
 160         if (annotations == null) {
 161             return new Annotation[javaMethod.signature.getParameterCount(false)][0];
 162         }
 163         return annotations;
 164     }
 165 
 166     @Override
 167     Type[] getGenericParameterTypes(HotSpotResolvedJavaMethodImpl javaMethod) {
 168         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 169     }
 170 
 171     @Override
 172     Annotation[] getFieldAnnotations(HotSpotResolvedJavaFieldImpl javaField) {
 173         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 174     }
 175 
 176     @Override
 177     Annotation[] getMethodAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
 178         Annotation[] annotations = getMethodAnnotationsInternal(javaMethod);
 179         return annotations == null ? new Annotation[0] : annotations;
 180     }
 181 
 182     @Override
 183     <T extends Annotation> T getMethodAnnotation(HotSpotResolvedJavaMethodImpl javaMethod, Class<T> annotationClass) {
 184         Annotation[] methodAnnotations = getMethodAnnotations(javaMethod);
 185         if (methodAnnotations != null) {
 186             for (Annotation ann : methodAnnotations) {
 187                 if (annotationClass.isInstance(ann)) {
 188                     return annotationClass.cast(ann);
 189                 }
 190             }
 191         }
 192         return null;
 193     }
 194 
 195     // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
 196     @SuppressWarnings("unused")
 197     private static Annotation[] getMethodAnnotationsInternal(ResolvedJavaMethod javaMethod) {
 198         throw new InternalError("missing substitution");
 199     }
 200 
 201     @Override
 202     Annotation[] getMethodDeclaredAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
 203         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 204     }
 205 
 206     @Override
 207     Annotation[] getFieldDeclaredAnnotations(HotSpotResolvedJavaFieldImpl javaMethod) {
 208         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 209     }
 210 
 211     @Override
 212     <T extends Annotation> T getFieldAnnotation(HotSpotResolvedJavaFieldImpl javaField, Class<T> annotationClass) {
 213         throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
 214     }
 215 
 216     @Override
 217     HotSpotResolvedObjectTypeImpl getType(HotSpotObjectConstantImpl object) {
 218         if (object instanceof DirectHotSpotObjectConstantImpl) {
 219             Class<?> theClass = ((DirectHotSpotObjectConstantImpl) object).object.getClass();
 220             try {
 221                 String name = theClass.getName().replace('.', '/');
 222                 HotSpotResolvedObjectTypeImpl type = (HotSpotResolvedObjectTypeImpl) runtime().compilerToVm.lookupType(name, null, true);
 223                 if (type == null) {
 224                     throw new InternalError(name);
 225                 }
 226                 return type;
 227             } catch (ClassNotFoundException e) {
 228                 throw new InternalError(e);
 229             }
 230         }
 231         return runtime().compilerToVm.getResolvedJavaType(object, runtime().getConfig().hubOffset, false);
 232     }
 233 
 234     @Override
 235     String asString(HotSpotObjectConstantImpl object) {
 236         if (object instanceof IndirectHotSpotObjectConstantImpl) {
 237             return runtime().compilerToVm.asString(object);
 238         }
 239         Object value = ((DirectHotSpotObjectConstantImpl) object).object;
 240         if (value instanceof String) {
 241             return (String) value;
 242         }
 243         return null;
 244     }
 245 
 246     @Override
 247     ResolvedJavaType asJavaType(HotSpotObjectConstantImpl object) {
 248         if (object instanceof DirectHotSpotObjectConstantImpl) {
 249             DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
 250             if (direct.object instanceof Class) {
 251                 Class<?> javaClass = (Class<?>) direct.object;
 252                 return runtime().fromClass(javaClass);
 253             }
 254             if (direct.object instanceof ResolvedJavaType) {
 255                 return (ResolvedJavaType) convertUnknownValue(direct.object);
 256             }
 257             return null;
 258         }
 259         return runtime().compilerToVm.asJavaType(object);
 260     }
 261 
 262     // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
 263     static Object convertUnknownValue(Object object) {
 264         return object;
 265     }
 266 
 267     @SuppressWarnings("unchecked")
 268     @Override
 269     <T> T asObject(HotSpotObjectConstantImpl object, Class<T> type) {
 270         if (object instanceof DirectHotSpotObjectConstantImpl) {
 271             Object theObject = ((DirectHotSpotObjectConstantImpl) object).object;
 272             if (type.isInstance(theObject)) {
 273                 return (T) convertUnknownValue(type.cast(theObject));
 274             }
 275         }
 276         return null;
 277     }
 278 
 279     @Override
 280     Object asObject(HotSpotObjectConstantImpl object, HotSpotResolvedJavaType type) {
 281         throw new HotSpotJVMCIUnsupportedOperationError("cannot resolve a shared library JVMCI object handle to a " +
 282                         "raw object as it may be in another runtime");
 283     }
 284 
 285     @Override
 286     String formatString(HotSpotObjectConstantImpl object) {
 287         if (object instanceof DirectHotSpotObjectConstantImpl) {
 288             DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
 289             return "CompilerObject<" + direct.object.getClass().getName() + ">";
 290         }
 291         return "Instance<" + object.getType().toJavaName() + ">";
 292     }
 293 
 294     @Override
 295     Integer getLength(HotSpotObjectConstantImpl object) {
 296         if (object instanceof DirectHotSpotObjectConstantImpl) {
 297             DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
 298             if (direct.object.getClass().isArray()) {
 299                 return Array.getLength(direct.object);
 300             }
 301             return null;
 302         }
 303         int length = runtime().compilerToVm.getArrayLength(object);
 304         if (length >= 0) {
 305             return length;
 306         }
 307         return null;
 308     }
 309 
 310     @Override
 311     JavaConstant readArrayElement(HotSpotObjectConstantImpl arrayObject, int index) {
 312         Object result = runtime().compilerToVm.readArrayElement(arrayObject, index);
 313         if (result == null) {
 314             return null;
 315         }
 316         if (result instanceof JavaConstant) {
 317             return (JavaConstant) result;
 318         }
 319         JavaConstant constant = JavaConstant.forBoxedPrimitive(result);
 320         if (constant == null) {
 321             throw new InternalError("Unexpected value " + result);
 322         }
 323         return constant;
 324     }
 325 
 326     @Override
 327     JavaConstant forObject(Object value) {
 328         return DirectHotSpotObjectConstantImpl.forObject(value, false);
 329     }
 330 
 331     @Override
 332     JavaConstant unboxPrimitive(HotSpotObjectConstantImpl source) {
 333         Object box = runtime().compilerToVm.unboxPrimitive(source);
 334         return JavaConstant.forBoxedPrimitive(box);
 335     }
 336 
 337     @Override
 338     JavaConstant boxPrimitive(JavaConstant source) {
 339         return runtime().compilerToVm.boxPrimitive(source.asBoxedPrimitive());
 340     }
 341 
 342     @Override
 343     int getInt(HotSpotObjectConstantImpl object, long displacement) {
 344         return runtime().compilerToVm.getInt(object, displacement);
 345     }
 346 
 347     @Override
 348     byte getByte(HotSpotObjectConstantImpl object, long displacement) {
 349         return runtime().compilerToVm.getByte(object, displacement);
 350     }
 351 
 352     @Override
 353     short getShort(HotSpotObjectConstantImpl object, long displacement) {
 354         return runtime().compilerToVm.getShort(object, displacement);
 355     }
 356 
 357     @Override
 358     long getLong(HotSpotObjectConstantImpl object, long displacement) {
 359         return runtime().compilerToVm.getLong(object, displacement);
 360     }
 361 
 362     @Override
 363     void checkRead(HotSpotObjectConstantImpl constant, JavaKind kind, long displacement, HotSpotResolvedObjectType type) {
 364 
 365     }
 366 }