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 } |