src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File open Sdiff src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot

src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java

Print this page


   1 /*
   2  * Copyright (c) 2011, 2018, 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 java.util.Objects.requireNonNull;
  26 import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
  27 import static jdk.vm.ci.hotspot.HotSpotConstantPool.isSignaturePolymorphicHolder;
  28 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
  29 import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmClassModifiers;
  30 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
  31 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
  32 
  33 import java.lang.annotation.Annotation;
  34 import java.lang.reflect.Array;
  35 import java.lang.reflect.Constructor;
  36 import java.lang.reflect.Field;
  37 import java.lang.reflect.Method;
  38 import java.lang.reflect.Modifier;
  39 import java.nio.ByteOrder;
  40 import java.util.HashMap;
  41 
  42 import jdk.vm.ci.common.JVMCIError;
  43 import jdk.vm.ci.meta.Assumptions.AssumptionResult;
  44 import jdk.vm.ci.meta.Assumptions.ConcreteMethod;
  45 import jdk.vm.ci.meta.Assumptions.ConcreteSubtype;
  46 import jdk.vm.ci.meta.Assumptions.LeafType;
  47 import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass;
  48 import jdk.vm.ci.meta.Constant;
  49 import jdk.vm.ci.meta.JavaConstant;
  50 import jdk.vm.ci.meta.JavaKind;
  51 import jdk.vm.ci.meta.JavaType;
  52 import jdk.vm.ci.meta.ResolvedJavaField;
  53 import jdk.vm.ci.meta.ResolvedJavaMethod;
  54 import jdk.vm.ci.meta.ResolvedJavaType;
  55 import jdk.vm.ci.meta.UnresolvedJavaField;
  56 import jdk.vm.ci.meta.UnresolvedJavaType;
  57 
  58 /**
  59  * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.


  60  */
  61 final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, MetaspaceWrapperObject {
  62 
  63     private static final HotSpotResolvedJavaField[] NO_FIELDS = new HotSpotResolvedJavaField[0];
  64     private static final int METHOD_CACHE_ARRAY_CAPACITY = 8;
  65 
  66     /**
  67      * The Java class this type represents.
  68      */
  69     private final Class<?> javaClass;

  70     private HotSpotResolvedJavaMethodImpl[] methodCacheArray;
  71     private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCacheHashMap;
  72     private HotSpotResolvedJavaField[] instanceFields;
  73     private HotSpotResolvedObjectTypeImpl[] interfaces;
  74     private HotSpotConstantPool constantPool;
  75     final HotSpotJVMCIMetaAccessContext context;
  76     private HotSpotResolvedObjectType arrayOfType;


  77 
  78     /**
  79      * Managed exclusively by {@link HotSpotResolvedJavaFieldImpl#toJava}.
  80      */
  81     HashMap<HotSpotResolvedJavaFieldImpl, Field> reflectionFieldCache;
  82 
  83     /**
  84      * Gets the JVMCI mirror for a {@link Class} object.
  85      *
  86      * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass}
  87      */
  88     static HotSpotResolvedObjectTypeImpl fromObjectClass(Class<?> javaClass) {
  89         return (HotSpotResolvedObjectTypeImpl) runtime().fromClass(javaClass);
  90     }
  91 
  92     /**
  93      * Gets the JVMCI mirror from a HotSpot type. Since {@link Class} is already a proxy for the
  94      * underlying Klass*, it is used instead of the raw Klass*.
  95      *
  96      * Called from the VM.
  97      *
  98      * @param javaClass a {@link Class} object
  99      * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
 100      */
 101     @SuppressWarnings("unused")
 102     private static HotSpotResolvedObjectTypeImpl fromMetaspace(Class<?> javaClass) {
 103         return fromObjectClass(javaClass);

 104     }
 105 
 106     /**
 107      * Creates the JVMCI mirror for a {@link Class} object.
 108      *
 109      * <p>
 110      * <b>NOTE</b>: Creating an instance of this class does not install the mirror for the
 111      * {@link Class} type. Use {@link #fromObjectClass(Class)} or {@link #fromMetaspace(Class)}
 112      * instead.
 113      * </p>
 114      *
 115      * @param javaClass the Class to create the mirror for
 116      * @param context
 117      */
 118     HotSpotResolvedObjectTypeImpl(Class<?> javaClass, HotSpotJVMCIMetaAccessContext context) {
 119         super(getSignatureName(javaClass));
 120         this.javaClass = javaClass;
 121         this.context = context;

 122         assert getName().charAt(0) != '[' || isArray() : getName();
 123     }
 124 
 125     /**
 126      * Returns the name of this type as it would appear in a signature.
 127      */
 128     private static String getSignatureName(Class<?> javaClass) {
 129         if (javaClass.isArray()) {
 130             return javaClass.getName().replace('.', '/');
 131         }
 132         return "L" + javaClass.getName().replace('.', '/') + ";";
 133     }
 134 
 135     /**
 136      * Gets the metaspace Klass for this type.
 137      */
 138     long getMetaspaceKlass() {
 139         if (HotSpotJVMCIRuntime.getHostWordKind() == JavaKind.Long) {
 140             return UNSAFE.getLong(javaClass, config().klassOffset);

 141         }
 142         return UNSAFE.getInt(javaClass, config().klassOffset) & 0xFFFFFFFFL;
 143     }
 144 
 145     @Override
 146     public long getMetaspacePointer() {
 147         return getMetaspaceKlass();
 148     }
 149 
 150     /**
 151      * The Klass* for this object is kept alive by the direct reference to {@link #javaClass} so no
 152      * extra work is required.
 153      */
 154     @Override
 155     public boolean isRegistered() {
 156         return true;
 157     }
 158 
 159     @Override
 160     public int getModifiers() {
 161         if (isArray()) {
 162             return (getElementalType().getModifiers() & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)) | Modifier.FINAL | Modifier.ABSTRACT;
 163         } else {
 164             return getAccessFlags() & jvmClassModifiers();
 165         }
 166     }
 167 
 168     public int getAccessFlags() {
 169         HotSpotVMConfig config = config();
 170         return UNSAFE.getInt(getMetaspaceKlass() + config.klassAccessFlagsOffset);
 171     }
 172 
 173     @Override
 174     public HotSpotResolvedObjectType getArrayClass() {
 175         if (arrayOfType == null) {
 176             arrayOfType = fromObjectClass(Array.newInstance(mirror(), 0).getClass());




 177         }
 178         return arrayOfType;
 179     }
 180 
 181     @Override
 182     public ResolvedJavaType getComponentType() {
 183         Class<?> javaComponentType = mirror().getComponentType();
 184         return javaComponentType == null ? null : runtime().fromClass(javaComponentType);
 185     }
 186 
 187     @Override
 188     public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
 189         if (isLeaf()) {
 190             // No assumptions are required.
 191             return new AssumptionResult<>(this);
 192         }
 193         HotSpotVMConfig config = config();
 194         if (isArray()) {
 195             ResolvedJavaType elementalType = getElementalType();
 196             AssumptionResult<ResolvedJavaType> elementType = elementalType.findLeafConcreteSubtype();
 197             if (elementType != null && elementType.getResult().equals(elementalType)) {
 198                 /*
 199                  * If the elementType is leaf then the array is leaf under the same assumptions but
 200                  * only if the element type is exactly the leaf type. The element type can be
 201                  * abstract even if there is only one implementor of the abstract type.
 202                  */
 203                 AssumptionResult<ResolvedJavaType> result = new AssumptionResult<>(this);
 204                 result.add(elementType);


 262      * {@code Klass::_subklass} field of the underlying class is zero.
 263      *
 264      * @return true if the type is a leaf class
 265      */
 266     private boolean isLeafClass() {
 267         return UNSAFE.getLong(this.getMetaspaceKlass() + config().subklassOffset) == 0;
 268     }
 269 
 270     /**
 271      * Returns the {@code Klass::_subklass} field of the underlying metaspace klass for the given
 272      * type {@code type}.
 273      *
 274      * @return value of the subklass field as metaspace klass pointer
 275      */
 276     private HotSpotResolvedObjectTypeImpl getSubklass() {
 277         return compilerToVM().getResolvedJavaType(this, config().subklassOffset, false);
 278     }
 279 
 280     @Override
 281     public HotSpotResolvedObjectTypeImpl getSuperclass() {
 282         Class<?> javaSuperclass = mirror().getSuperclass();
 283         return javaSuperclass == null ? null : fromObjectClass(javaSuperclass);














 284     }
 285 
 286     @Override
 287     public HotSpotResolvedObjectTypeImpl[] getInterfaces() {
 288         if (interfaces == null) {
 289             Class<?>[] javaInterfaces = mirror().getInterfaces();
 290             HotSpotResolvedObjectTypeImpl[] result = new HotSpotResolvedObjectTypeImpl[javaInterfaces.length];
 291             for (int i = 0; i < javaInterfaces.length; i++) {
 292                 result[i] = fromObjectClass(javaInterfaces[i]);



 293             }
 294             interfaces = result;
 295         }
 296         return interfaces;
 297     }
 298 
 299     @Override
 300     public HotSpotResolvedObjectTypeImpl getSingleImplementor() {
 301         if (!isInterface()) {
 302             throw new JVMCIError("Cannot call getSingleImplementor() on a non-interface type: %s", this);
 303         }
 304         return compilerToVM().getImplementor(this);
 305     }
 306 
 307     @Override
 308     public HotSpotResolvedObjectTypeImpl getSupertype() {
 309         if (isArray()) {
 310             ResolvedJavaType componentType = getComponentType();
 311             if (mirror() == Object[].class || componentType.isPrimitive()) {
 312                 return fromObjectClass(Object.class);
 313             }
 314             return (HotSpotResolvedObjectTypeImpl) ((HotSpotResolvedObjectTypeImpl) componentType).getSupertype().getArrayClass();

 315         }
 316         if (isInterface()) {
 317             return fromObjectClass(Object.class);
 318         }
 319         return getSuperclass();
 320     }
 321 
 322     @Override
 323     public HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType) {
 324         if (otherType.isPrimitive()) {
 325             return null;
 326         } else {
 327             HotSpotResolvedObjectTypeImpl t1 = this;
 328             HotSpotResolvedObjectTypeImpl t2 = (HotSpotResolvedObjectTypeImpl) otherType;
 329             while (true) {
 330                 if (t1.isAssignableFrom(t2)) {
 331                     return t1;
 332                 }
 333                 if (t2.isAssignableFrom(t1)) {
 334                     return t2;
 335                 }
 336                 t1 = t1.getSupertype();
 337                 t2 = t2.getSupertype();
 338             }
 339         }
 340     }
 341 
 342     @Override
 343     public AssumptionResult<Boolean> hasFinalizableSubclass() {
 344         assert !isArray();
 345         if (!compilerToVM().hasFinalizableSubclass(this)) {
 346             return new AssumptionResult<>(false, new NoFinalizableSubclass(this));
 347         }
 348         return new AssumptionResult<>(true);
 349     }
 350 
 351     @Override
 352     public boolean hasFinalizer() {
 353         return (getAccessFlags() & config().jvmAccHasFinalizer) != 0;
 354     }
 355 
 356     @Override
 357     public boolean isPrimitive() {
 358         return false;
 359     }
 360 
 361     @Override
 362     public boolean isArray() {
 363         return mirror().isArray();
 364     }
 365 
 366     @Override
 367     public boolean isEnum() {
 368         return mirror().isEnum();

 369     }
 370 
 371     @Override
 372     public boolean isInitialized() {
 373         return isArray() ? true : getInitState() == config().instanceKlassStateFullyInitialized;
 374     }
 375 
 376     @Override
 377     public boolean isLinked() {
 378         return isArray() ? true : getInitState() >= config().instanceKlassStateLinked;
 379     }
 380 
 381     /**
 382      * Returns the value of the state field {@code InstanceKlass::_init_state} of the metaspace
 383      * klass.
 384      *
 385      * @return state field value of this type
 386      */
 387     private int getInitState() {
 388         assert !isArray() : "_init_state only exists in InstanceKlass";
 389         return UNSAFE.getByte(getMetaspaceKlass() + config().instanceKlassInitStateOffset) & 0xFF;
 390     }
 391 
 392     @Override
 393     public void initialize() {
 394         if (!isInitialized()) {
 395             UNSAFE.ensureClassInitialized(mirror());
 396             assert isInitialized();
 397         }
 398     }
 399 
 400     @Override
 401     public boolean isInstance(JavaConstant obj) {
 402         if (obj.getJavaKind() == JavaKind.Object && !obj.isNull()) {
 403             return mirror().isInstance(((HotSpotObjectConstantImpl) obj).object());
 404         }
 405         return false;
 406     }
 407 
 408     @Override
 409     public boolean isInstanceClass() {
 410         return !isArray() && !isInterface();
 411     }
 412 
 413     @Override
 414     public boolean isInterface() {
 415         return mirror().isInterface();
 416     }
 417 
 418     @Override
 419     public boolean isAssignableFrom(ResolvedJavaType other) {
 420         assert other != null;
 421         if (other instanceof HotSpotResolvedObjectTypeImpl) {
 422             HotSpotResolvedObjectTypeImpl otherType = (HotSpotResolvedObjectTypeImpl) other;
 423             return mirror().isAssignableFrom(otherType.mirror());
 424         }
 425         return false;
 426     }
 427 
 428     @Override
 429     public ResolvedJavaType getHostClass() {
 430         if (isArray()) {
 431             return null;
 432         }
 433         return compilerToVM().getHostClass(this);
 434     }
 435 
 436     @Override
 437     public boolean isJavaLangObject() {
 438         return javaClass.equals(Object.class);
 439     }
 440 
 441     @Override
 442     public JavaKind getJavaKind() {
 443         return JavaKind.Object;
 444     }
 445 
 446     @Override
 447     public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
 448         assert !callerType.isArray();
 449         if (isInterface()) {
 450             // Methods can only be resolved against concrete types
 451             return null;
 452         }
 453         if (method.isConcrete() && method.getDeclaringClass().equals(this) && method.isPublic() && !isSignaturePolymorphicHolder(method.getDeclaringClass())) {
 454             return method;
 455         }
 456         if (!method.getDeclaringClass().isAssignableFrom(this)) {
 457             return null;
 458         }


 484     public int instanceSize() {
 485         assert !isArray();
 486         assert !isInterface();
 487 
 488         HotSpotVMConfig config = config();
 489         final int layoutHelper = layoutHelper();
 490         assert layoutHelper > config.klassLayoutHelperNeutralValue : "must be instance";
 491 
 492         // See: Klass::layout_helper_size_in_bytes
 493         int size = layoutHelper & ~config.klassLayoutHelperInstanceSlowPathBit;
 494 
 495         // See: Klass::layout_helper_needs_slow_path
 496         boolean needsSlowPath = (layoutHelper & config.klassLayoutHelperInstanceSlowPathBit) != 0;
 497 
 498         return needsSlowPath ? -size : size;
 499     }
 500 
 501     @Override
 502     public int layoutHelper() {
 503         HotSpotVMConfig config = config();

 504         return UNSAFE.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
 505     }
 506 
 507     @Override
 508     public long getFingerprint() {
 509         return compilerToVM().getFingerprint(getMetaspaceKlass());
 510     }
 511 
 512     synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {

 513         // Maintain cache as array.
 514         if (methodCacheArray == null) {
 515             methodCacheArray = new HotSpotResolvedJavaMethodImpl[METHOD_CACHE_ARRAY_CAPACITY];
 516         }
 517 
 518         int i = 0;
 519         for (; i < methodCacheArray.length; ++i) {
 520             HotSpotResolvedJavaMethodImpl curMethod = methodCacheArray[i];
 521             if (curMethod == null) {
 522                 HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
 523                 methodCacheArray[i] = newMethod;
 524                 context.add(newMethod);
 525                 return newMethod;
 526             } else if (curMethod.getMetaspacePointer() == metaspaceMethod) {
 527                 return curMethod;
 528             }
 529         }
 530 
 531         // Fall-back to hash table.
 532         if (methodCacheHashMap == null) {
 533             methodCacheHashMap = new HashMap<>();
 534         }
 535 
 536         HotSpotResolvedJavaMethodImpl lookupResult = methodCacheHashMap.get(metaspaceMethod);
 537         if (lookupResult == null) {
 538             HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
 539             methodCacheHashMap.put(metaspaceMethod, newMethod);
 540             context.add(lookupResult);
 541             return newMethod;
 542         } else {
 543             return lookupResult;
 544         }
 545     }
 546 
 547     @Override
 548     public int getVtableLength() {
 549         HotSpotVMConfig config = config();
 550         if (isInterface() || isArray()) {
 551             /* Everything has the core vtable of java.lang.Object */
 552             return config.baseVtableLength();
 553         }
 554         int result = UNSAFE.getInt(getMetaspaceKlass() + config.klassVtableLengthOffset) / (config.vtableEntrySize / config.heapWordSize);
 555         assert result >= config.baseVtableLength() : UNSAFE.getInt(getMetaspaceKlass() + config.klassVtableLengthOffset) + " " + config.vtableEntrySize;
 556         return result;
 557     }
 558 
 559     HotSpotResolvedJavaField createField(JavaType type, long offset, int rawFlags, int index) {
 560         return new HotSpotResolvedJavaFieldImpl(this, type, offset, rawFlags, index);


 582          * The holder may be a subtype of the declaredHolder so make sure to resolve the method to
 583          * the correct method for the subtype.
 584          */
 585         HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) resolveMethod(hmethod, this);
 586         if (resolvedMethod == null) {
 587             // The type isn't known to implement the method.
 588             return null;
 589         }
 590 
 591         ResolvedJavaMethod result = resolvedMethod.uniqueConcreteMethod(this);
 592         if (result != null) {
 593             return new AssumptionResult<>(result, new ConcreteMethod(method, this, result));
 594         }
 595         return null;
 596     }
 597 
 598     FieldInfo createFieldInfo(int index) {
 599         return new FieldInfo(index);
 600     }
 601 





















 602     /**
 603      * This class represents the field information for one field contained in the fields array of an
 604      * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
 605      */
 606     class FieldInfo {
 607         /**
 608          * Native pointer into the array of Java shorts.
 609          */
 610         private final long metaspaceData;
 611 
 612         /**
 613          * Creates a field info for the field in the fields array at index {@code index}.
 614          *
 615          * @param index index to the fields array
 616          */
 617         FieldInfo(int index) {
 618             HotSpotVMConfig config = config();
 619             // Get Klass::_fields
 620             final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
 621             assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code";


 765         for (int i = 0; i < index; ++i) {
 766             FieldInfo field = new FieldInfo(i);
 767             if (field.isStatic() == retrieveStaticFields) {
 768                 int offset = field.getOffset();
 769                 HotSpotResolvedJavaField resolvedJavaField = createField(field.getType(), offset, field.getAccessFlags(), i);
 770 
 771                 // Make sure the result is sorted by offset.
 772                 int j;
 773                 for (j = resultIndex - 1; j >= prependLength && result[j].getOffset() > offset; j--) {
 774                     result[j + 1] = result[j];
 775                 }
 776                 result[j + 1] = resolvedJavaField;
 777                 resultIndex++;
 778             }
 779         }
 780 
 781         return result;
 782     }
 783 
 784     @Override
 785     public Class<?> mirror() {
 786         return javaClass;
 787     }
 788 
 789     @Override
 790     public String getSourceFileName() {
 791         HotSpotVMConfig config = config();
 792         final int sourceFileNameIndex = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassSourceFileNameIndexOffset);
 793         if (sourceFileNameIndex == 0) {
 794             return null;
 795         }
 796         return getConstantPool().lookupUtf8(sourceFileNameIndex);
 797     }
 798 
 799     @Override
 800     public Annotation[] getAnnotations() {
 801         return mirror().getAnnotations();
 802     }
 803 
 804     @Override
 805     public Annotation[] getDeclaredAnnotations() {
 806         return mirror().getDeclaredAnnotations();
 807     }
 808 
 809     @Override
 810     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
 811         return mirror().getAnnotation(annotationClass);
 812     }
 813 
 814     /**
 815      * Performs a fast-path check that this type is resolved in the context of a given accessing
 816      * class. A negative result does not mean this type is not resolved with respect to
 817      * {@code accessingClass}. That can only be determined by
 818      * {@linkplain HotSpotJVMCIRuntime#lookupType(String, HotSpotResolvedObjectType, boolean)
 819      * re-resolving} the type.
 820      */
 821     @Override
 822     public boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass) {
 823         assert accessingClass != null;
 824         ResolvedJavaType elementType = getElementalType();
 825         if (elementType.isPrimitive()) {
 826             // Primitive type resolution is context free.
 827             return true;
 828         }
 829         if (elementType.getName().startsWith("Ljava/")) {
 830             // Classes in a java.* package can only be defined by the
 831             // boot or platform class loader.

 832             return true;
 833         }
 834         ClassLoader thisCl = mirror().getClassLoader();
 835         ClassLoader accessingClassCl = ((HotSpotResolvedObjectTypeImpl) accessingClass).mirror().getClassLoader();
 836         return thisCl == accessingClassCl;




 837     }
 838 
 839     @Override
 840     public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
 841         if (isDefinitelyResolvedWithRespectTo(requireNonNull(accessingClass))) {
 842             return this;
 843         }
 844         HotSpotResolvedObjectTypeImpl accessingType = (HotSpotResolvedObjectTypeImpl) accessingClass;
 845         return (ResolvedJavaType) runtime().lookupType(getName(), accessingType, true);
 846     }
 847 
 848     /**
 849      * Gets the metaspace Klass boxed in a {@link JavaConstant}.
 850      */
 851     @Override
 852     public Constant klass() {
 853         return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false);
 854     }
 855 
 856     @Override


 870         if (isArray()) {
 871             return config.arrayPrototypeMarkWord();
 872         } else {
 873             return UNSAFE.getAddress(getMetaspaceKlass() + config.prototypeMarkWordOffset);
 874         }
 875     }
 876 
 877     @Override
 878     public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedEntryKind) {
 879         ResolvedJavaField[] declaredFields = getInstanceFields(true);
 880         return findFieldWithOffset(offset, expectedEntryKind, declaredFields);
 881     }
 882 
 883     public ResolvedJavaField findStaticFieldWithOffset(long offset, JavaKind expectedEntryKind) {
 884         ResolvedJavaField[] declaredFields = getStaticFields();
 885         return findFieldWithOffset(offset, expectedEntryKind, declaredFields);
 886     }
 887 
 888     private static ResolvedJavaField findFieldWithOffset(long offset, JavaKind expectedEntryKind, ResolvedJavaField[] declaredFields) {
 889         for (ResolvedJavaField field : declaredFields) {
 890             HotSpotResolvedJavaField resolvedField = (HotSpotResolvedJavaField) field;
 891             long resolvedFieldOffset = resolvedField.getOffset();
 892             // @formatter:off
 893             if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN  &&
 894                             expectedEntryKind.isPrimitive() &&
 895                             !expectedEntryKind.equals(JavaKind.Void) &&
 896                             resolvedField.getJavaKind().isPrimitive()) {
 897                 resolvedFieldOffset +=
 898                                 resolvedField.getJavaKind().getByteCount() -
 899                                 Math.min(resolvedField.getJavaKind().getByteCount(), 4 + expectedEntryKind.getByteCount());
 900             }
 901             if (resolvedFieldOffset == offset) {
 902                 return field;
 903             }
 904             // @formatter:on
 905         }
 906         return null;
 907     }
 908 
 909     @Override
 910     public boolean isLocal() {
 911         return mirror().isLocalClass();
 912     }
 913 
 914     @Override
 915     public boolean isMember() {
 916         return mirror().isMemberClass();
 917     }
 918 
 919     @Override
 920     public HotSpotResolvedObjectTypeImpl getEnclosingType() {
 921         final Class<?> encl = mirror().getEnclosingClass();
 922         return encl == null ? null : fromObjectClass(encl);
 923     }
 924 
 925     @Override
 926     public ResolvedJavaMethod[] getDeclaredConstructors() {
 927         Constructor<?>[] constructors = mirror().getDeclaredConstructors();
 928         ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length];
 929         for (int i = 0; i < constructors.length; i++) {
 930             result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(constructors[i]);
 931             assert result[i].isConstructor();
 932         }
 933         return result;
 934     }
 935 
 936     @Override
 937     public ResolvedJavaMethod[] getDeclaredMethods() {
 938         Method[] methods = mirror().getDeclaredMethods();
 939         ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length];
 940         for (int i = 0; i < methods.length; i++) {
 941             result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(methods[i]);
 942             assert !result[i].isConstructor();
 943         }
 944         return result;
 945     }
 946 
 947     @Override
 948     public ResolvedJavaMethod getClassInitializer() {
 949         if (!isArray()) {
 950             return compilerToVM().getClassInitializer(this);
 951         }
 952         return null;
 953     }
 954 
 955     @Override
 956     public String toString() {
 957         return "HotSpotType<" + getName() + ", resolved>";
 958     }
 959 
 960     @Override
 961     public ResolvedJavaType lookupType(UnresolvedJavaType unresolvedJavaType, boolean resolve) {
 962         JavaType javaType = HotSpotJVMCIRuntime.runtime().lookupType(unresolvedJavaType.getName(), this, resolve);
 963         if (javaType instanceof ResolvedJavaType) {
 964             return (ResolvedJavaType) javaType;


 969     @Override
 970     public ResolvedJavaField resolveField(UnresolvedJavaField unresolvedJavaField, ResolvedJavaType accessingClass) {
 971         for (ResolvedJavaField field : getInstanceFields(false)) {
 972             if (field.getName().equals(unresolvedJavaField.getName())) {
 973                 return field;
 974             }
 975         }
 976         for (ResolvedJavaField field : getStaticFields()) {
 977             if (field.getName().equals(unresolvedJavaField.getName())) {
 978                 return field;
 979             }
 980         }
 981         throw new InternalError(unresolvedJavaField.toString());
 982     }
 983 
 984     @Override
 985     public boolean isCloneableWithAllocation() {
 986         return (getAccessFlags() & config().jvmAccIsCloneableFast) != 0;
 987     }
 988 




 989     private int getMiscFlags() {
 990         return UNSAFE.getInt(getMetaspaceKlass() + config().instanceKlassMiscFlagsOffset);
 991     }
 992 
 993     @Override
 994     public boolean isUnsafeAnonymous() {
 995         return (getMiscFlags() & config().instanceKlassMiscIsUnsafeAnonymous) != 0;
 996     }
 997 
 998 }
   1 /*
   2  * Copyright (c) 2011, 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 java.util.Objects.requireNonNull;
  26 import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
  27 import static jdk.vm.ci.hotspot.HotSpotConstantPool.isSignaturePolymorphicHolder;
  28 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
  29 import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmClassModifiers;
  30 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
  31 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
  32 
  33 import java.lang.annotation.Annotation;


  34 import java.lang.reflect.Field;

  35 import java.lang.reflect.Modifier;
  36 import java.nio.ByteOrder;
  37 import java.util.HashMap;
  38 
  39 import jdk.vm.ci.common.JVMCIError;
  40 import jdk.vm.ci.meta.Assumptions.AssumptionResult;
  41 import jdk.vm.ci.meta.Assumptions.ConcreteMethod;
  42 import jdk.vm.ci.meta.Assumptions.ConcreteSubtype;
  43 import jdk.vm.ci.meta.Assumptions.LeafType;
  44 import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass;
  45 import jdk.vm.ci.meta.Constant;
  46 import jdk.vm.ci.meta.JavaConstant;
  47 import jdk.vm.ci.meta.JavaKind;
  48 import jdk.vm.ci.meta.JavaType;
  49 import jdk.vm.ci.meta.ResolvedJavaField;
  50 import jdk.vm.ci.meta.ResolvedJavaMethod;
  51 import jdk.vm.ci.meta.ResolvedJavaType;
  52 import jdk.vm.ci.meta.UnresolvedJavaField;
  53 import jdk.vm.ci.meta.UnresolvedJavaType;
  54 
  55 /**
  56  * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes. This class is not
  57  * an {@link MetaspaceHandleObject} because it doesn't have to be scanned for GC. It's liveness is
  58  * maintained by a reference to the {@link Class} instance.
  59  */
  60 final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, MetaspaceObject {
  61 
  62     private static final HotSpotResolvedJavaField[] NO_FIELDS = new HotSpotResolvedJavaField[0];
  63     private static final int METHOD_CACHE_ARRAY_CAPACITY = 8;
  64 
  65     /**
  66      * The Java class this type represents.
  67      */
  68     private final long metadataPointer;
  69 
  70     private HotSpotResolvedJavaMethodImpl[] methodCacheArray;
  71     private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCacheHashMap;
  72     private volatile HotSpotResolvedJavaField[] instanceFields;
  73     private volatile HotSpotResolvedObjectTypeImpl[] interfaces;
  74     private HotSpotConstantPool constantPool;

  75     private HotSpotResolvedObjectType arrayOfType;
  76     private final JavaConstant mirror;
  77     private HotSpotResolvedObjectTypeImpl superClass;
  78 
  79     /**
  80      * Managed exclusively by {@link HotSpotJDKReflection#getField}.
  81      */
  82     HashMap<HotSpotResolvedJavaFieldImpl, Field> reflectionFieldCache;
  83 
  84     static HotSpotResolvedObjectTypeImpl getJavaLangObject() {
  85         return runtime().getJavaLangObject();





  86     }
  87 
  88     /**
  89      * Gets the JVMCI mirror from a HotSpot type.

  90      *
  91      * Called from the VM.
  92      *
  93      * @param klassPointer a native pointer to the Klass*
  94      * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
  95      */
  96     @SuppressWarnings("unused")
  97     @VMEntryPoint
  98     private static HotSpotResolvedObjectTypeImpl fromMetaspace(long klassPointer, String signature) {
  99         return runtime().fromMetaspace(klassPointer, signature);
 100     }
 101 
 102     /**
 103      * Creates the JVMCI mirror for a {@link Class} object.
 104      *

 105      * <b>NOTE</b>: Creating an instance of this class does not install the mirror for the
 106      * {@link Class} type. {@link #fromMetaspace} instead.

 107      * </p>
 108      *
 109      * @param metadataPointer the Klass* to create the mirror for

 110      */
 111     HotSpotResolvedObjectTypeImpl(long metadataPointer, String name) {
 112         super(name);
 113         this.metadataPointer = metadataPointer;
 114         this.mirror = runtime().compilerToVm.getJavaMirror(this);
 115         assert metadataPointer != 0;
 116         assert getName().charAt(0) != '[' || isArray() : getName();
 117     }
 118 
 119     /**










 120      * Gets the metaspace Klass for this type.
 121      */
 122     long getMetaspaceKlass() {
 123         long metaspacePointer = getMetaspacePointer();
 124         if (metaspacePointer == 0) {
 125             throw new NullPointerException("Klass* is null");
 126         }
 127         return metaspacePointer;
 128     }
 129 
 130     @Override
 131     public long getMetaspacePointer() {
 132         return metadataPointer;









 133     }
 134 
 135     @Override
 136     public int getModifiers() {
 137         if (isArray()) {
 138             return (getElementalType().getModifiers() & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)) | Modifier.FINAL | Modifier.ABSTRACT;
 139         } else {
 140             return getAccessFlags() & jvmClassModifiers();
 141         }
 142     }
 143 
 144     public int getAccessFlags() {
 145         HotSpotVMConfig config = config();
 146         return UNSAFE.getInt(getMetaspaceKlass() + config.klassAccessFlagsOffset);
 147     }
 148 
 149     @Override
 150     public HotSpotResolvedObjectType getArrayClass() {
 151         if (arrayOfType == null) {
 152             try {
 153                 arrayOfType = (HotSpotResolvedObjectType) runtime().compilerToVm.lookupType("[" + getName(), this, true);
 154             } catch (ClassNotFoundException e) {
 155                 throw new JVMCIError(e);
 156             }
 157         }
 158         return arrayOfType;
 159     }
 160 
 161     @Override
 162     public ResolvedJavaType getComponentType() {
 163         return runtime().compilerToVm.getComponentType(this);

 164     }
 165 
 166     @Override
 167     public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
 168         if (isLeaf()) {
 169             // No assumptions are required.
 170             return new AssumptionResult<>(this);
 171         }
 172         HotSpotVMConfig config = config();
 173         if (isArray()) {
 174             ResolvedJavaType elementalType = getElementalType();
 175             AssumptionResult<ResolvedJavaType> elementType = elementalType.findLeafConcreteSubtype();
 176             if (elementType != null && elementType.getResult().equals(elementalType)) {
 177                 /*
 178                  * If the elementType is leaf then the array is leaf under the same assumptions but
 179                  * only if the element type is exactly the leaf type. The element type can be
 180                  * abstract even if there is only one implementor of the abstract type.
 181                  */
 182                 AssumptionResult<ResolvedJavaType> result = new AssumptionResult<>(this);
 183                 result.add(elementType);


 241      * {@code Klass::_subklass} field of the underlying class is zero.
 242      *
 243      * @return true if the type is a leaf class
 244      */
 245     private boolean isLeafClass() {
 246         return UNSAFE.getLong(this.getMetaspaceKlass() + config().subklassOffset) == 0;
 247     }
 248 
 249     /**
 250      * Returns the {@code Klass::_subklass} field of the underlying metaspace klass for the given
 251      * type {@code type}.
 252      *
 253      * @return value of the subklass field as metaspace klass pointer
 254      */
 255     private HotSpotResolvedObjectTypeImpl getSubklass() {
 256         return compilerToVM().getResolvedJavaType(this, config().subklassOffset, false);
 257     }
 258 
 259     @Override
 260     public HotSpotResolvedObjectTypeImpl getSuperclass() {
 261         if (isInterface()) {
 262             return null;
 263         }
 264         HotSpotResolvedObjectTypeImpl javaLangObject = runtime().getJavaLangObject();
 265         if (this.equals(javaLangObject)) {
 266             return null;
 267         }
 268         if (isArray()) {
 269             return javaLangObject;
 270         }
 271 
 272         // Cache result of native call
 273         if (superClass == null) {
 274             superClass = compilerToVM().getResolvedJavaType(this, config().superOffset, false);
 275         }
 276         return superClass;
 277     }
 278 
 279     @Override
 280     public HotSpotResolvedObjectTypeImpl[] getInterfaces() {
 281         if (interfaces == null) {
 282             if (isArray()) {
 283                 HotSpotResolvedObjectTypeImpl[] types = new HotSpotResolvedObjectTypeImpl[2];
 284                 types[0] = runtime().getJavaLangCloneable();
 285                 types[1] = runtime().getJavaLangSerializable();
 286                 this.interfaces = types;
 287             } else {
 288                 interfaces = runtime().compilerToVm.getInterfaces(this);
 289             }

 290         }
 291         return interfaces;
 292     }
 293 
 294     @Override
 295     public HotSpotResolvedObjectTypeImpl getSingleImplementor() {
 296         if (!isInterface()) {
 297             throw new JVMCIError("Cannot call getSingleImplementor() on a non-interface type: %s", this);
 298         }
 299         return compilerToVM().getImplementor(this);
 300     }
 301 
 302     @Override
 303     public HotSpotResolvedObjectTypeImpl getSupertype() {
 304         if (isArray()) {
 305             ResolvedJavaType componentType = getComponentType();
 306             if (componentType.equals(getJavaLangObject()) || componentType.isPrimitive()) {
 307                 return getJavaLangObject();
 308             }
 309             HotSpotResolvedObjectTypeImpl supertype = ((HotSpotResolvedObjectTypeImpl) componentType).getSupertype();
 310             return (HotSpotResolvedObjectTypeImpl) supertype.getArrayClass();
 311         }
 312         if (isInterface()) {
 313             return getJavaLangObject();
 314         }
 315         return getSuperclass();
 316     }
 317 
 318     @Override
 319     public HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType) {
 320         if (otherType.isPrimitive()) {
 321             return null;
 322         } else {
 323             HotSpotResolvedObjectTypeImpl t1 = this;
 324             HotSpotResolvedObjectTypeImpl t2 = (HotSpotResolvedObjectTypeImpl) otherType;
 325             while (true) {
 326                 if (t1.isAssignableFrom(t2)) {
 327                     return t1;
 328                 }
 329                 if (t2.isAssignableFrom(t1)) {
 330                     return t2;
 331                 }
 332                 t1 = t1.getSupertype();
 333                 t2 = t2.getSupertype();
 334             }
 335         }
 336     }
 337 
 338     @Override
 339     public AssumptionResult<Boolean> hasFinalizableSubclass() {
 340         assert !isArray();
 341         if (!compilerToVM().hasFinalizableSubclass(this)) {
 342             return new AssumptionResult<>(false, new NoFinalizableSubclass(this));
 343         }
 344         return new AssumptionResult<>(true);
 345     }
 346 
 347     @Override
 348     public boolean hasFinalizer() {
 349         return (getAccessFlags() & config().jvmAccHasFinalizer) != 0;
 350     }
 351 
 352     @Override





 353     public boolean isArray() {
 354         return layoutHelper() < config().klassLayoutHelperNeutralValue;
 355     }
 356 
 357     @Override
 358     public boolean isEnum() {
 359         HotSpotResolvedObjectTypeImpl superclass = getSuperclass();
 360         return superclass != null && superclass.equals(runtime().getJavaLangEnum());
 361     }
 362 
 363     @Override
 364     public boolean isInitialized() {
 365         return isArray() ? true : getInitState() == config().instanceKlassStateFullyInitialized;
 366     }
 367 
 368     @Override
 369     public boolean isLinked() {
 370         return isArray() ? true : getInitState() >= config().instanceKlassStateLinked;
 371     }
 372 
 373     /**
 374      * Returns the value of the state field {@code InstanceKlass::_init_state} of the metaspace
 375      * klass.
 376      *
 377      * @return state field value of this type
 378      */
 379     private int getInitState() {
 380         assert !isArray() : "_init_state only exists in InstanceKlass";
 381         return UNSAFE.getByte(getMetaspaceKlass() + config().instanceKlassInitStateOffset) & 0xFF;
 382     }
 383 
 384     @Override
 385     public void initialize() {
 386         if (!isInitialized()) {
 387             runtime().compilerToVm.ensureInitialized(this);
 388             assert isInitialized();
 389         }
 390     }
 391 
 392     @Override
 393     public boolean isInstance(JavaConstant obj) {
 394         if (obj.getJavaKind() == JavaKind.Object && !obj.isNull()) {
 395             return runtime().reflection.isInstance(this, (HotSpotObjectConstantImpl) obj);
 396         }
 397         return false;
 398     }
 399 
 400     @Override
 401     public boolean isInstanceClass() {
 402         return !isArray() && !isInterface();
 403     }
 404 
 405     @Override
 406     public boolean isInterface() {
 407         return (getAccessFlags() & config().jvmAccInterface) != 0;
 408     }
 409 
 410     @Override
 411     public boolean isAssignableFrom(ResolvedJavaType other) {
 412         assert other != null;
 413         if (other instanceof HotSpotResolvedObjectTypeImpl) {
 414             HotSpotResolvedObjectTypeImpl otherType = (HotSpotResolvedObjectTypeImpl) other;
 415             return runtime().reflection.isAssignableFrom(this, otherType);
 416         }
 417         return false;
 418     }
 419 
 420     @Override
 421     public ResolvedJavaType getHostClass() {
 422         if (isArray()) {
 423             return null;
 424         }
 425         return compilerToVM().getHostClass(this);
 426     }
 427 
 428     @Override
 429     public boolean isJavaLangObject() {
 430         return getName().equals("Ljava/lang/Object;");
 431     }
 432 
 433     @Override
 434     public JavaKind getJavaKind() {
 435         return JavaKind.Object;
 436     }
 437 
 438     @Override
 439     public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
 440         assert !callerType.isArray();
 441         if (isInterface()) {
 442             // Methods can only be resolved against concrete types
 443             return null;
 444         }
 445         if (method.isConcrete() && method.getDeclaringClass().equals(this) && method.isPublic() && !isSignaturePolymorphicHolder(method.getDeclaringClass())) {
 446             return method;
 447         }
 448         if (!method.getDeclaringClass().isAssignableFrom(this)) {
 449             return null;
 450         }


 476     public int instanceSize() {
 477         assert !isArray();
 478         assert !isInterface();
 479 
 480         HotSpotVMConfig config = config();
 481         final int layoutHelper = layoutHelper();
 482         assert layoutHelper > config.klassLayoutHelperNeutralValue : "must be instance";
 483 
 484         // See: Klass::layout_helper_size_in_bytes
 485         int size = layoutHelper & ~config.klassLayoutHelperInstanceSlowPathBit;
 486 
 487         // See: Klass::layout_helper_needs_slow_path
 488         boolean needsSlowPath = (layoutHelper & config.klassLayoutHelperInstanceSlowPathBit) != 0;
 489 
 490         return needsSlowPath ? -size : size;
 491     }
 492 
 493     @Override
 494     public int layoutHelper() {
 495         HotSpotVMConfig config = config();
 496         assert getMetaspaceKlass() != 0 : getName();
 497         return UNSAFE.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
 498     }
 499 
 500     @Override
 501     public long getFingerprint() {
 502         return compilerToVM().getFingerprint(getMetaspaceKlass());
 503     }
 504 
 505     synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceHandle) {
 506         long metaspaceMethod = UNSAFE.getLong(metaspaceHandle);
 507         // Maintain cache as array.
 508         if (methodCacheArray == null) {
 509             methodCacheArray = new HotSpotResolvedJavaMethodImpl[METHOD_CACHE_ARRAY_CAPACITY];
 510         }
 511 
 512         int i = 0;
 513         for (; i < methodCacheArray.length; ++i) {
 514             HotSpotResolvedJavaMethodImpl curMethod = methodCacheArray[i];
 515             if (curMethod == null) {
 516                 HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceHandle);
 517                 methodCacheArray[i] = newMethod;

 518                 return newMethod;
 519             } else if (curMethod.getMetaspaceMethod() == metaspaceMethod) {
 520                 return curMethod;
 521             }
 522         }
 523 
 524         // Fall-back to hash table.
 525         if (methodCacheHashMap == null) {
 526             methodCacheHashMap = new HashMap<>();
 527         }
 528 
 529         HotSpotResolvedJavaMethodImpl lookupResult = methodCacheHashMap.get(metaspaceMethod);
 530         if (lookupResult == null) {
 531             HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceHandle);
 532             methodCacheHashMap.put(metaspaceMethod, newMethod);

 533             return newMethod;
 534         } else {
 535             return lookupResult;
 536         }
 537     }
 538 
 539     @Override
 540     public int getVtableLength() {
 541         HotSpotVMConfig config = config();
 542         if (isInterface() || isArray()) {
 543             /* Everything has the core vtable of java.lang.Object */
 544             return config.baseVtableLength();
 545         }
 546         int result = UNSAFE.getInt(getMetaspaceKlass() + config.klassVtableLengthOffset) / (config.vtableEntrySize / config.heapWordSize);
 547         assert result >= config.baseVtableLength() : UNSAFE.getInt(getMetaspaceKlass() + config.klassVtableLengthOffset) + " " + config.vtableEntrySize;
 548         return result;
 549     }
 550 
 551     HotSpotResolvedJavaField createField(JavaType type, long offset, int rawFlags, int index) {
 552         return new HotSpotResolvedJavaFieldImpl(this, type, offset, rawFlags, index);


 574          * The holder may be a subtype of the declaredHolder so make sure to resolve the method to
 575          * the correct method for the subtype.
 576          */
 577         HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) resolveMethod(hmethod, this);
 578         if (resolvedMethod == null) {
 579             // The type isn't known to implement the method.
 580             return null;
 581         }
 582 
 583         ResolvedJavaMethod result = resolvedMethod.uniqueConcreteMethod(this);
 584         if (result != null) {
 585             return new AssumptionResult<>(result, new ConcreteMethod(method, this, result));
 586         }
 587         return null;
 588     }
 589 
 590     FieldInfo createFieldInfo(int index) {
 591         return new FieldInfo(index);
 592     }
 593 
 594     public void ensureInitialized() {
 595         runtime().compilerToVm.ensureInitialized(this);
 596     }
 597 
 598     @Override
 599     public boolean equals(Object obj) {
 600         if (obj == this) {
 601             return true;
 602         }
 603         if (!(obj instanceof HotSpotResolvedObjectTypeImpl)) {
 604             return false;
 605         }
 606         HotSpotResolvedObjectTypeImpl that = (HotSpotResolvedObjectTypeImpl) obj;
 607         return getMetaspaceKlass() == that.getMetaspaceKlass();
 608     }
 609 
 610     @Override
 611     JavaConstant getJavaMirror() {
 612         return mirror;
 613     }
 614 
 615     /**
 616      * This class represents the field information for one field contained in the fields array of an
 617      * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
 618      */
 619     class FieldInfo {
 620         /**
 621          * Native pointer into the array of Java shorts.
 622          */
 623         private final long metaspaceData;
 624 
 625         /**
 626          * Creates a field info for the field in the fields array at index {@code index}.
 627          *
 628          * @param index index to the fields array
 629          */
 630         FieldInfo(int index) {
 631             HotSpotVMConfig config = config();
 632             // Get Klass::_fields
 633             final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
 634             assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code";


 778         for (int i = 0; i < index; ++i) {
 779             FieldInfo field = new FieldInfo(i);
 780             if (field.isStatic() == retrieveStaticFields) {
 781                 int offset = field.getOffset();
 782                 HotSpotResolvedJavaField resolvedJavaField = createField(field.getType(), offset, field.getAccessFlags(), i);
 783 
 784                 // Make sure the result is sorted by offset.
 785                 int j;
 786                 for (j = resultIndex - 1; j >= prependLength && result[j].getOffset() > offset; j--) {
 787                     result[j + 1] = result[j];
 788                 }
 789                 result[j + 1] = resolvedJavaField;
 790                 resultIndex++;
 791             }
 792         }
 793 
 794         return result;
 795     }
 796 
 797     @Override





 798     public String getSourceFileName() {
 799         HotSpotVMConfig config = config();
 800         final int sourceFileNameIndex = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassSourceFileNameIndexOffset);
 801         if (sourceFileNameIndex == 0) {
 802             return null;
 803         }
 804         return getConstantPool().lookupUtf8(sourceFileNameIndex);
 805     }
 806 
 807     @Override
 808     public Annotation[] getAnnotations() {
 809         return runtime().reflection.getAnnotations(this);
 810     }
 811 
 812     @Override
 813     public Annotation[] getDeclaredAnnotations() {
 814         return runtime().reflection.getDeclaredAnnotations(this);
 815     }
 816 
 817     @Override
 818     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
 819         return runtime().reflection.getAnnotation(this, annotationClass);
 820     }
 821 
 822     /**
 823      * Performs a fast-path check that this type is resolved in the context of a given accessing
 824      * class. A negative result does not mean this type is not resolved with respect to
 825      * {@code accessingClass}. That can only be determined by
 826      * {@linkplain HotSpotJVMCIRuntime#lookupType(String, HotSpotResolvedObjectType, boolean)
 827      * re-resolving} the type.
 828      */
 829     @Override
 830     public boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass) {
 831         assert accessingClass != null;
 832         ResolvedJavaType elementType = getElementalType();
 833         if (elementType.isPrimitive()) {
 834             // Primitive type resolution is context free.
 835             return true;
 836         }
 837         if (elementType.getName().startsWith("Ljava/")) {
 838             // Classes in a java.* package can only be defined by the
 839             // boot class loader. This is enforced by ClassLoader.preDefineClass()
 840             assert hasSameClassLoader(runtime().getJavaLangObject());
 841             return true;
 842         }
 843         HotSpotResolvedObjectTypeImpl otherMirror = ((HotSpotResolvedObjectTypeImpl) accessingClass);
 844         return hasSameClassLoader(otherMirror);
 845     }
 846 
 847     private boolean hasSameClassLoader(HotSpotResolvedObjectTypeImpl otherMirror) {
 848         return UnsafeAccess.UNSAFE.getAddress(getMetaspaceKlass() + config().classLoaderDataOffset) == UnsafeAccess.UNSAFE.getAddress(
 849                         otherMirror.getMetaspaceKlass() + config().classLoaderDataOffset);
 850     }
 851 
 852     @Override
 853     public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
 854         if (isDefinitelyResolvedWithRespectTo(requireNonNull(accessingClass))) {
 855             return this;
 856         }
 857         HotSpotResolvedObjectTypeImpl accessingType = (HotSpotResolvedObjectTypeImpl) accessingClass;
 858         return (ResolvedJavaType) runtime().lookupType(getName(), accessingType, true);
 859     }
 860 
 861     /**
 862      * Gets the metaspace Klass boxed in a {@link JavaConstant}.
 863      */
 864     @Override
 865     public Constant klass() {
 866         return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false);
 867     }
 868 
 869     @Override


 883         if (isArray()) {
 884             return config.arrayPrototypeMarkWord();
 885         } else {
 886             return UNSAFE.getAddress(getMetaspaceKlass() + config.prototypeMarkWordOffset);
 887         }
 888     }
 889 
 890     @Override
 891     public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedEntryKind) {
 892         ResolvedJavaField[] declaredFields = getInstanceFields(true);
 893         return findFieldWithOffset(offset, expectedEntryKind, declaredFields);
 894     }
 895 
 896     public ResolvedJavaField findStaticFieldWithOffset(long offset, JavaKind expectedEntryKind) {
 897         ResolvedJavaField[] declaredFields = getStaticFields();
 898         return findFieldWithOffset(offset, expectedEntryKind, declaredFields);
 899     }
 900 
 901     private static ResolvedJavaField findFieldWithOffset(long offset, JavaKind expectedEntryKind, ResolvedJavaField[] declaredFields) {
 902         for (ResolvedJavaField field : declaredFields) {
 903             long resolvedFieldOffset = field.getOffset();

 904             // @formatter:off
 905             if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN &&
 906                     expectedEntryKind.isPrimitive() &&
 907                     !expectedEntryKind.equals(JavaKind.Void) &&
 908                     field.getJavaKind().isPrimitive()) {
 909                 resolvedFieldOffset +=
 910                         field.getJavaKind().getByteCount() -
 911                                 Math.min(field.getJavaKind().getByteCount(), 4 + expectedEntryKind.getByteCount());
 912             }
 913             if (resolvedFieldOffset == offset) {
 914                 return field;
 915             }
 916             // @formatter:on
 917         }
 918         return null;
 919     }
 920 
 921     @Override
 922     public boolean isLocal() {
 923         return runtime().reflection.isLocalClass(this);
 924     }
 925 
 926     @Override
 927     public boolean isMember() {
 928         return runtime().reflection.isMemberClass(this);
 929     }
 930 
 931     @Override
 932     public HotSpotResolvedObjectType getEnclosingType() {
 933         return runtime().reflection.getEnclosingClass(this);

 934     }
 935 
 936     @Override
 937     public ResolvedJavaMethod[] getDeclaredConstructors() {
 938         return runtime().compilerToVm.getDeclaredConstructors(this);






 939     }
 940 
 941     @Override
 942     public ResolvedJavaMethod[] getDeclaredMethods() {
 943         return runtime().compilerToVm.getDeclaredMethods(this);






 944     }
 945 
 946     @Override
 947     public ResolvedJavaMethod getClassInitializer() {
 948         if (!isArray()) {
 949             return compilerToVM().getClassInitializer(this);
 950         }
 951         return null;
 952     }
 953 
 954     @Override
 955     public String toString() {
 956         return "HotSpotType<" + getName() + ", resolved>";
 957     }
 958 
 959     @Override
 960     public ResolvedJavaType lookupType(UnresolvedJavaType unresolvedJavaType, boolean resolve) {
 961         JavaType javaType = HotSpotJVMCIRuntime.runtime().lookupType(unresolvedJavaType.getName(), this, resolve);
 962         if (javaType instanceof ResolvedJavaType) {
 963             return (ResolvedJavaType) javaType;


 968     @Override
 969     public ResolvedJavaField resolveField(UnresolvedJavaField unresolvedJavaField, ResolvedJavaType accessingClass) {
 970         for (ResolvedJavaField field : getInstanceFields(false)) {
 971             if (field.getName().equals(unresolvedJavaField.getName())) {
 972                 return field;
 973             }
 974         }
 975         for (ResolvedJavaField field : getStaticFields()) {
 976             if (field.getName().equals(unresolvedJavaField.getName())) {
 977                 return field;
 978             }
 979         }
 980         throw new InternalError(unresolvedJavaField.toString());
 981     }
 982 
 983     @Override
 984     public boolean isCloneableWithAllocation() {
 985         return (getAccessFlags() & config().jvmAccIsCloneableFast) != 0;
 986     }
 987 
 988     JavaConstant readFieldValue(HotSpotResolvedJavaField field, boolean isVolatile) {
 989         return runtime().reflection.readFieldValue(this, field, isVolatile);
 990     }
 991 
 992     private int getMiscFlags() {
 993         return UNSAFE.getInt(getMetaspaceKlass() + config().instanceKlassMiscFlagsOffset);
 994     }
 995 
 996     @Override
 997     public boolean isUnsafeAnonymous() {
 998         return (getMiscFlags() & config().instanceKlassMiscIsUnsafeAnonymous) != 0;
 999     }
1000 
1001 }
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File