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.*;
26 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
27 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
28
29 import java.lang.annotation.*;
30 import java.lang.reflect.*;
31 import java.net.*;
32 import java.nio.*;
33 import java.util.*;
34
35 import jdk.vm.ci.common.*;
36 import jdk.vm.ci.meta.*;
37 import jdk.vm.ci.meta.Assumptions.*;
38
39 /**
40 * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.
41 */
42 public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, HotSpotProxified, MetaspaceWrapperObject {
43
44 /**
45 * The Java class this type represents.
46 */
47 private final Class<?> javaClass;
48 private HashMap<Long, HotSpotResolvedJavaField> fieldCache;
49 private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCache;
50 private HotSpotResolvedJavaField[] instanceFields;
51 private HotSpotResolvedObjectTypeImpl[] interfaces;
52 private HotSpotConstantPool constantPool;
53 final HotSpotJVMCIMetaAccessContext context;
54 private HotSpotResolvedObjectType arrayOfType;
55
56 /**
57 * Gets the JVMCI mirror for a {@link Class} object.
58 *
59 * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass}
60 */
61 public static HotSpotResolvedObjectTypeImpl fromObjectClass(Class<?> javaClass) {
62 return (HotSpotResolvedObjectTypeImpl) runtime().fromClass(javaClass);
63 }
64
65 /**
66 * Gets the JVMCI mirror from a HotSpot type. Since {@link Class} is already a proxy for the
67 * underlying Klass*, it is used instead of the raw Klass*.
68 *
69 * Called from the VM.
70 *
71 * @param javaClass a {@link Class} object
72 * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
73 */
74 @SuppressWarnings("unused")
75 private static HotSpotResolvedObjectTypeImpl fromMetaspace(Class<?> javaClass) {
76 return fromObjectClass(javaClass);
77 }
78
79 /**
80 * Creates the JVMCI mirror for a {@link Class} object.
81 *
91 HotSpotResolvedObjectTypeImpl(Class<?> javaClass, HotSpotJVMCIMetaAccessContext context) {
92 super(getSignatureName(javaClass));
93 this.javaClass = javaClass;
94 this.context = context;
95 assert getName().charAt(0) != '[' || isArray() : getName();
96 }
97
98 /**
99 * Returns the name of this type as it would appear in a signature.
100 */
101 private static String getSignatureName(Class<?> javaClass) {
102 if (javaClass.isArray()) {
103 return javaClass.getName().replace('.', '/');
104 }
105 return "L" + javaClass.getName().replace('.', '/') + ";";
106 }
107
108 /**
109 * Gets the metaspace Klass for this type.
110 */
111 public long getMetaspaceKlass() {
112 if (HotSpotJVMCIRuntime.getHostWordKind() == JavaKind.Long) {
113 return UNSAFE.getLong(javaClass, (long) runtime().getConfig().klassOffset);
114 }
115 return UNSAFE.getInt(javaClass, (long) runtime().getConfig().klassOffset) & 0xFFFFFFFFL;
116 }
117
118 public long getMetaspacePointer() {
119 return getMetaspaceKlass();
120 }
121
122 @Override
123 public int getModifiers() {
124 if (isArray()) {
125 return (getElementalType().getModifiers() & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)) | Modifier.FINAL | Modifier.ABSTRACT;
126 } else {
127 return getAccessFlags() & ModifiersProvider.jvmClassModifiers();
128 }
129 }
130
131 public int getAccessFlags() {
132 HotSpotVMConfig config = runtime().getConfig();
133 return UNSAFE.getInt(getMetaspaceKlass() + config.klassAccessFlagsOffset);
134 }
135
136 @Override
137 public HotSpotResolvedObjectType getArrayClass() {
138 if (arrayOfType == null) {
139 arrayOfType = fromObjectClass(Array.newInstance(mirror(), 0).getClass());
140 }
141 return arrayOfType;
142 }
143
144 @Override
145 public ResolvedJavaType getComponentType() {
146 Class<?> javaComponentType = mirror().getComponentType();
147 return javaComponentType == null ? null : runtime().fromClass(javaComponentType);
148 }
149
150 @Override
151 public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
152 HotSpotVMConfig config = runtime().getConfig();
153 if (isArray()) {
154 return getElementalType().isLeaf() ? new AssumptionResult<>(this) : null;
155 } else if (isInterface()) {
156 HotSpotResolvedObjectTypeImpl implementor = getSingleImplementor();
157 /*
158 * If the implementor field contains itself that indicates that the interface has more
159 * than one implementors (see: InstanceKlass::add_implementor).
160 */
161 if (implementor == null || implementor.equals(this)) {
162 return null;
163 }
164
165 assert !implementor.isInterface();
166 if (implementor.isAbstract() || !implementor.isLeafClass()) {
167 AssumptionResult<ResolvedJavaType> leafConcreteSubtype = implementor.findLeafConcreteSubtype();
168 if (leafConcreteSubtype != null) {
169 assert !leafConcreteSubtype.getResult().equals(implementor);
170 AssumptionResult<ResolvedJavaType> newResult = new AssumptionResult<>(leafConcreteSubtype.getResult(), new ConcreteSubtype(this, implementor));
171 // Accumulate leaf assumptions and return the combined result.
172 newResult.add(leafConcreteSubtype);
197 }
198 }
199
200 /**
201 * Returns if type {@code type} is a leaf class. This is the case if the
202 * {@code Klass::_subklass} field of the underlying class is zero.
203 *
204 * @return true if the type is a leaf class
205 */
206 private boolean isLeafClass() {
207 return getSubklass() == null;
208 }
209
210 /**
211 * Returns the {@code Klass::_subklass} field of the underlying metaspace klass for the given
212 * type {@code type}.
213 *
214 * @return value of the subklass field as metaspace klass pointer
215 */
216 private HotSpotResolvedObjectTypeImpl getSubklass() {
217 return runtime().getCompilerToVM().getResolvedJavaType(this, runtime().getConfig().subklassOffset, false);
218 }
219
220 @Override
221 public HotSpotResolvedObjectTypeImpl getSuperclass() {
222 Class<?> javaSuperclass = mirror().getSuperclass();
223 return javaSuperclass == null ? null : fromObjectClass(javaSuperclass);
224 }
225
226 @Override
227 public HotSpotResolvedObjectTypeImpl[] getInterfaces() {
228 if (interfaces == null) {
229 Class<?>[] javaInterfaces = mirror().getInterfaces();
230 HotSpotResolvedObjectTypeImpl[] result = new HotSpotResolvedObjectTypeImpl[javaInterfaces.length];
231 for (int i = 0; i < javaInterfaces.length; i++) {
232 result[i] = fromObjectClass(javaInterfaces[i]);
233 }
234 interfaces = result;
235 }
236 return interfaces;
237 }
238
239 @Override
240 public HotSpotResolvedObjectTypeImpl getSingleImplementor() {
241 if (!isInterface()) {
242 throw new JVMCIError("Cannot call getSingleImplementor() on a non-interface type: %s", this);
243 }
244 return runtime().getCompilerToVM().getImplementor(this);
245 }
246
247 public HotSpotResolvedObjectTypeImpl getSupertype() {
248 if (isArray()) {
249 ResolvedJavaType componentType = getComponentType();
250 if (mirror() == Object[].class || componentType.isPrimitive()) {
251 return fromObjectClass(Object.class);
252 }
253 return (HotSpotResolvedObjectTypeImpl) ((HotSpotResolvedObjectTypeImpl) componentType).getSupertype().getArrayClass();
254 }
255 if (isInterface()) {
256 return fromObjectClass(Object.class);
257 }
258 return getSuperclass();
259 }
260
261 @Override
262 public HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType) {
263 if (otherType.isPrimitive()) {
264 return null;
272 if (t2.isAssignableFrom(t1)) {
273 return t2;
274 }
275 t1 = t1.getSupertype();
276 t2 = t2.getSupertype();
277 }
278 }
279 }
280
281 @Override
282 public HotSpotResolvedObjectType asExactType() {
283 return isLeaf() ? this : null;
284 }
285
286 @Override
287 public JavaConstant getJavaClass() {
288 return HotSpotObjectConstantImpl.forObject(mirror());
289 }
290
291 @Override
292 public JavaConstant getObjectHub() {
293 return klass();
294 }
295
296 @Override
297 public AssumptionResult<Boolean> hasFinalizableSubclass() {
298 assert !isArray();
299 if (!runtime().getCompilerToVM().hasFinalizableSubclass(this)) {
300 return new AssumptionResult<>(false, new NoFinalizableSubclass(this));
301 }
302 return new AssumptionResult<>(true);
303 }
304
305 @Override
306 public boolean hasFinalizer() {
307 HotSpotVMConfig config = runtime().getConfig();
308 return (getAccessFlags() & config.klassHasFinalizerFlag) != 0;
309 }
310
311 @Override
312 public boolean isPrimitive() {
313 return false;
314 }
315
316 @Override
317 public boolean isArray() {
318 return mirror().isArray();
319 }
320
321 @Override
322 public boolean isInitialized() {
323 return isArray() ? true : getInitState() == runtime().getConfig().instanceKlassStateFullyInitialized;
324 }
325
326 @Override
327 public boolean isLinked() {
328 return isArray() ? true : getInitState() >= runtime().getConfig().instanceKlassStateLinked;
329 }
330
331 /**
332 * Returns the value of the state field {@code InstanceKlass::_init_state} of the metaspace
333 * klass.
334 *
335 * @return state field value of this type
336 */
337 private int getInitState() {
338 assert !isArray() : "_init_state only exists in InstanceKlass";
339 return UNSAFE.getByte(getMetaspaceKlass() + runtime().getConfig().instanceKlassInitStateOffset) & 0xFF;
340 }
341
342 @Override
343 public void initialize() {
344 if (!isInitialized()) {
345 UNSAFE.ensureClassInitialized(mirror());
346 assert isInitialized();
347 }
348 }
349
350 @Override
351 public boolean isInstance(JavaConstant obj) {
352 if (obj.getJavaKind() == JavaKind.Object && !obj.isNull()) {
353 return mirror().isInstance(((HotSpotObjectConstantImpl) obj).object());
354 }
355 return false;
356 }
357
358 @Override
359 public boolean isInstanceClass() {
388 @Override
389 public ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
390 ResolvedJavaMethod resolvedMethod = resolveMethod(method, callerType);
391 if (resolvedMethod == null || resolvedMethod.isAbstract()) {
392 return null;
393 }
394 return resolvedMethod;
395 }
396
397 @Override
398 public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
399 assert !callerType.isArray();
400 if (method.isConcrete() && method.getDeclaringClass().equals(this) && method.isPublic()) {
401 return method;
402 }
403 if (!method.getDeclaringClass().isAssignableFrom(this)) {
404 return null;
405 }
406 HotSpotResolvedJavaMethodImpl hotSpotMethod = (HotSpotResolvedJavaMethodImpl) method;
407 HotSpotResolvedObjectTypeImpl hotSpotCallerType = (HotSpotResolvedObjectTypeImpl) callerType;
408 return runtime().getCompilerToVM().resolveMethod(this, hotSpotMethod, hotSpotCallerType);
409 }
410
411 public HotSpotConstantPool getConstantPool() {
412 if (constantPool == null) {
413 constantPool = runtime().getCompilerToVM().getConstantPool(this, runtime().getConfig().instanceKlassConstantsOffset);
414 }
415 return constantPool;
416 }
417
418 /**
419 * Gets the instance size of this type. If an instance of this type cannot be fast path
420 * allocated, then the returned value is negative (its absolute value gives the size). Must not
421 * be called if this is an array or interface type.
422 */
423 public int instanceSize() {
424 assert !isArray();
425 assert !isInterface();
426
427 HotSpotVMConfig config = runtime().getConfig();
428 final int layoutHelper = layoutHelper();
429 assert layoutHelper > config.klassLayoutHelperNeutralValue : "must be instance";
430
431 // See: Klass::layout_helper_size_in_bytes
432 int size = layoutHelper & ~config.klassLayoutHelperInstanceSlowPathBit;
433
434 // See: Klass::layout_helper_needs_slow_path
435 boolean needsSlowPath = (layoutHelper & config.klassLayoutHelperInstanceSlowPathBit) != 0;
436
437 return needsSlowPath ? -size : size;
438 }
439
440 public int layoutHelper() {
441 HotSpotVMConfig config = runtime().getConfig();
442 return UNSAFE.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
443 }
444
445 synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
446 HotSpotResolvedJavaMethodImpl method = null;
447 if (methodCache == null) {
448 methodCache = new HashMap<>(8);
449 } else {
450 method = methodCache.get(metaspaceMethod);
451 }
452 if (method == null) {
453 method = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
454 methodCache.put(metaspaceMethod, method);
455 context.add(method);
456 }
457 return method;
458 }
459
460 public int getVtableLength() {
461 HotSpotVMConfig config = runtime().getConfig();
462 if (isInterface() || isArray()) {
463 /* Everything has the core vtable of java.lang.Object */
464 return config.baseVtableLength();
465 }
466 int result = UNSAFE.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) / (config.vtableEntrySize / config.heapWordSize);
467 assert result >= config.baseVtableLength() : UNSAFE.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) + " " + config.vtableEntrySize;
468 return result;
469 }
470
471 public synchronized HotSpotResolvedJavaField createField(String fieldName, JavaType type, long offset, int rawFlags) {
472 HotSpotResolvedJavaField result = null;
473
474 final int flags = rawFlags & ModifiersProvider.jvmFieldModifiers();
475
476 final long id = offset + ((long) flags << 32);
477
478 // Must cache the fields, because the local load elimination only works if the
479 // objects from two field lookups are identical.
480 if (fieldCache == null) {
481 fieldCache = new HashMap<>(8);
530 }
531 return null;
532 }
533
534 /**
535 * This class represents the field information for one field contained in the fields array of an
536 * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
537 */
538 private class FieldInfo {
539 /**
540 * Native pointer into the array of Java shorts.
541 */
542 private final long metaspaceData;
543
544 /**
545 * Creates a field info for the field in the fields array at index {@code index}.
546 *
547 * @param index index to the fields array
548 */
549 public FieldInfo(int index) {
550 HotSpotVMConfig config = runtime().getConfig();
551 // Get Klass::_fields
552 final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
553 assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code";
554 metaspaceData = metaspaceFields + config.arrayU2DataOffset + config.fieldInfoFieldSlots * Short.BYTES * index;
555 }
556
557 private int getAccessFlags() {
558 return readFieldSlot(runtime().getConfig().fieldInfoAccessFlagsOffset);
559 }
560
561 private int getNameIndex() {
562 return readFieldSlot(runtime().getConfig().fieldInfoNameIndexOffset);
563 }
564
565 private int getSignatureIndex() {
566 return readFieldSlot(runtime().getConfig().fieldInfoSignatureIndexOffset);
567 }
568
569 public int getOffset() {
570 HotSpotVMConfig config = runtime().getConfig();
571 final int lowPacked = readFieldSlot(config.fieldInfoLowPackedOffset);
572 final int highPacked = readFieldSlot(config.fieldInfoHighPackedOffset);
573 final int offset = ((highPacked << Short.SIZE) | lowPacked) >> config.fieldInfoTagSize;
574 return offset;
575 }
576
577 /**
578 * Helper method to read an entry (slot) from the field array. Currently field info is laid
579 * on top an array of Java shorts.
580 */
581 private int readFieldSlot(int index) {
582 return UNSAFE.getChar(metaspaceData + Short.BYTES * index);
583 }
584
585 /**
586 * Returns the name of this field as a {@link String}. If the field is an internal field the
587 * name index is pointing into the vmSymbols table.
588 */
589 public String getName() {
590 final int nameIndex = getNameIndex();
591 return isInternal() ? HotSpotVmSymbols.symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex);
592 }
593
594 /**
595 * Returns the signature of this field as {@link String}. If the field is an internal field
596 * the signature index is pointing into the vmSymbols table.
597 */
598 public String getSignature() {
599 final int signatureIndex = getSignatureIndex();
600 return isInternal() ? HotSpotVmSymbols.symbolAt(signatureIndex) : getConstantPool().lookupUtf8(signatureIndex);
601 }
602
603 public JavaType getType() {
604 String signature = getSignature();
605 return runtime().lookupType(signature, HotSpotResolvedObjectTypeImpl.this, false);
606 }
607
608 private boolean isInternal() {
609 return (getAccessFlags() & runtime().getConfig().jvmAccFieldInternal) != 0;
610 }
611
612 public boolean isStatic() {
613 return Modifier.isStatic(getAccessFlags());
614 }
615
616 public boolean hasGenericSignature() {
617 return (getAccessFlags() & runtime().getConfig().jvmAccFieldHasGenericSignature) != 0;
618 }
619 }
620
621 private static class OffsetComparator implements java.util.Comparator<HotSpotResolvedJavaField> {
622 @Override
623 public int compare(HotSpotResolvedJavaField o1, HotSpotResolvedJavaField o2) {
624 return o1.offset() - o2.offset();
625 }
626 }
627
628 @Override
629 public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
630 if (instanceFields == null) {
631 if (isArray() || isInterface()) {
632 instanceFields = new HotSpotResolvedJavaField[0];
633 } else {
634 final int fieldCount = getFieldCount();
635 ArrayList<HotSpotResolvedJavaField> fieldsArray = new ArrayList<>(fieldCount);
636
637 for (int i = 0; i < fieldCount; i++) {
690 // We are only interested in static fields.
691 if (field.isStatic()) {
692 HotSpotResolvedJavaField resolvedJavaField = createField(field.getName(), field.getType(), field.getOffset(), field.getAccessFlags());
693 fieldsArray.add(resolvedJavaField);
694 }
695 }
696
697 fieldsArray.sort(new OffsetComparator());
698 return fieldsArray.toArray(new HotSpotResolvedJavaField[fieldsArray.size()]);
699 }
700 }
701
702 /**
703 * Returns the actual field count of this class's internal {@code InstanceKlass::_fields} array
704 * by walking the array and discounting the generic signature slots at the end of the array.
705 *
706 * <p>
707 * See {@code FieldStreamBase::init_generic_signature_start_slot}
708 */
709 private int getFieldCount() {
710 HotSpotVMConfig config = runtime().getConfig();
711 final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
712 int metaspaceFieldsLength = UNSAFE.getInt(metaspaceFields + config.arrayU1LengthOffset);
713 int fieldCount = 0;
714
715 for (int i = 0, index = 0; i < metaspaceFieldsLength; i += config.fieldInfoFieldSlots, index++) {
716 FieldInfo field = new FieldInfo(index);
717 if (field.hasGenericSignature()) {
718 metaspaceFieldsLength--;
719 }
720 fieldCount++;
721 }
722 return fieldCount;
723 }
724
725 @Override
726 public Class<?> mirror() {
727 return javaClass;
728 }
729
730 @Override
731 public String getSourceFileName() {
732 HotSpotVMConfig config = runtime().getConfig();
733 final int sourceFileNameIndex = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassSourceFileNameIndexOffset);
734 if (sourceFileNameIndex == 0) {
735 return null;
736 }
737 return getConstantPool().lookupUtf8(sourceFileNameIndex);
738 }
739
740 @Override
741 public Annotation[] getAnnotations() {
742 return mirror().getAnnotations();
743 }
744
745 @Override
746 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
747 return mirror().getAnnotation(annotationClass);
748 }
749
750 /**
751 * Performs a fast-path check that this type is resolved in the context of a given accessing
752 * class. A negative result does not mean this type is not resolved with respect to
767 assert mirror().getClassLoader() == null;
768 return true;
769 }
770 ClassLoader thisCl = mirror().getClassLoader();
771 ClassLoader accessingClassCl = ((HotSpotResolvedObjectTypeImpl) accessingClass).mirror().getClassLoader();
772 return thisCl == accessingClassCl;
773 }
774
775 @Override
776 public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
777 if (isDefinitelyResolvedWithRespectTo(requireNonNull(accessingClass))) {
778 return this;
779 }
780 HotSpotResolvedObjectTypeImpl accessingType = (HotSpotResolvedObjectTypeImpl) accessingClass;
781 return (ResolvedJavaType) runtime().lookupType(getName(), accessingType, true);
782 }
783
784 /**
785 * Gets the metaspace Klass boxed in a {@link JavaConstant}.
786 */
787 public JavaConstant klass() {
788 return HotSpotMetaspaceConstantImpl.forMetaspaceObject(runtime().getHostJVMCIBackend().getTarget().wordKind, getMetaspaceKlass(), this, false);
789 }
790
791 public boolean isPrimaryType() {
792 return runtime().getConfig().secondarySuperCacheOffset != superCheckOffset();
793 }
794
795 public int superCheckOffset() {
796 HotSpotVMConfig config = runtime().getConfig();
797 return UNSAFE.getInt(getMetaspaceKlass() + config.superCheckOffsetOffset);
798 }
799
800 public long prototypeMarkWord() {
801 HotSpotVMConfig config = runtime().getConfig();
802 if (isArray()) {
803 return config.arrayPrototypeMarkWord();
804 } else {
805 return UNSAFE.getAddress(getMetaspaceKlass() + config.prototypeMarkWordOffset);
806 }
807 }
808
809 @Override
810 public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedEntryKind) {
811 ResolvedJavaField[] declaredFields = getInstanceFields(true);
812 for (ResolvedJavaField field : declaredFields) {
813 HotSpotResolvedJavaField resolvedField = (HotSpotResolvedJavaField) field;
814 long resolvedFieldOffset = resolvedField.offset();
815 // @formatter:off
816 if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN &&
817 expectedEntryKind.isPrimitive() &&
818 !expectedEntryKind.equals(JavaKind.Void) &&
819 resolvedField.getJavaKind().isPrimitive()) {
820 resolvedFieldOffset +=
821 resolvedField.getJavaKind().getByteCount() -
857 ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length];
858 for (int i = 0; i < constructors.length; i++) {
859 result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(constructors[i]);
860 assert result[i].isConstructor();
861 }
862 return result;
863 }
864
865 @Override
866 public ResolvedJavaMethod[] getDeclaredMethods() {
867 Method[] methods = mirror().getDeclaredMethods();
868 ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length];
869 for (int i = 0; i < methods.length; i++) {
870 result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(methods[i]);
871 assert !result[i].isConstructor();
872 }
873 return result;
874 }
875
876 public ResolvedJavaMethod getClassInitializer() {
877 return runtime().getCompilerToVM().getClassInitializer(this);
878 }
879
880 @Override
881 public String toString() {
882 return "HotSpotType<" + getName() + ", resolved>";
883 }
884
885 @Override
886 public boolean isTrustedInterfaceType() {
887 return TrustedInterface.class.isAssignableFrom(mirror());
888 }
889 }
|
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.HotSpotJVMCIRuntime.runtime;
28 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
29 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
30
31 import java.lang.annotation.Annotation;
32 import java.lang.reflect.Array;
33 import java.lang.reflect.Constructor;
34 import java.lang.reflect.Method;
35 import java.lang.reflect.Modifier;
36 import java.net.URL;
37 import java.nio.ByteOrder;
38 import java.util.ArrayList;
39 import java.util.Arrays;
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.MetaUtil;
53 import jdk.vm.ci.meta.ModifiersProvider;
54 import jdk.vm.ci.meta.ResolvedJavaField;
55 import jdk.vm.ci.meta.ResolvedJavaMethod;
56 import jdk.vm.ci.meta.ResolvedJavaType;
57 import jdk.vm.ci.meta.TrustedInterface;
58
59 /**
60 * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.
61 */
62 final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, HotSpotProxified, MetaspaceWrapperObject {
63
64 /**
65 * The Java class this type represents.
66 */
67 private final Class<?> javaClass;
68 private HashMap<Long, HotSpotResolvedJavaField> fieldCache;
69 private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCache;
70 private HotSpotResolvedJavaField[] instanceFields;
71 private HotSpotResolvedObjectTypeImpl[] interfaces;
72 private HotSpotConstantPool constantPool;
73 final HotSpotJVMCIMetaAccessContext context;
74 private HotSpotResolvedObjectType arrayOfType;
75
76 /**
77 * Gets the JVMCI mirror for a {@link Class} object.
78 *
79 * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass}
80 */
81 static HotSpotResolvedObjectTypeImpl fromObjectClass(Class<?> javaClass) {
82 return (HotSpotResolvedObjectTypeImpl) runtime().fromClass(javaClass);
83 }
84
85 /**
86 * Gets the JVMCI mirror from a HotSpot type. Since {@link Class} is already a proxy for the
87 * underlying Klass*, it is used instead of the raw Klass*.
88 *
89 * Called from the VM.
90 *
91 * @param javaClass a {@link Class} object
92 * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
93 */
94 @SuppressWarnings("unused")
95 private static HotSpotResolvedObjectTypeImpl fromMetaspace(Class<?> javaClass) {
96 return fromObjectClass(javaClass);
97 }
98
99 /**
100 * Creates the JVMCI mirror for a {@link Class} object.
101 *
111 HotSpotResolvedObjectTypeImpl(Class<?> javaClass, HotSpotJVMCIMetaAccessContext context) {
112 super(getSignatureName(javaClass));
113 this.javaClass = javaClass;
114 this.context = context;
115 assert getName().charAt(0) != '[' || isArray() : getName();
116 }
117
118 /**
119 * Returns the name of this type as it would appear in a signature.
120 */
121 private static String getSignatureName(Class<?> javaClass) {
122 if (javaClass.isArray()) {
123 return javaClass.getName().replace('.', '/');
124 }
125 return "L" + javaClass.getName().replace('.', '/') + ";";
126 }
127
128 /**
129 * Gets the metaspace Klass for this type.
130 */
131 long getMetaspaceKlass() {
132 if (HotSpotJVMCIRuntime.getHostWordKind() == JavaKind.Long) {
133 return UNSAFE.getLong(javaClass, (long) config().klassOffset);
134 }
135 return UNSAFE.getInt(javaClass, (long) config().klassOffset) & 0xFFFFFFFFL;
136 }
137
138 public long getMetaspacePointer() {
139 return getMetaspaceKlass();
140 }
141
142 @Override
143 public int getModifiers() {
144 if (isArray()) {
145 return (getElementalType().getModifiers() & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)) | Modifier.FINAL | Modifier.ABSTRACT;
146 } else {
147 return getAccessFlags() & ModifiersProvider.jvmClassModifiers();
148 }
149 }
150
151 public int getAccessFlags() {
152 HotSpotVMConfig config = config();
153 return UNSAFE.getInt(getMetaspaceKlass() + config.klassAccessFlagsOffset);
154 }
155
156 @Override
157 public HotSpotResolvedObjectType getArrayClass() {
158 if (arrayOfType == null) {
159 arrayOfType = fromObjectClass(Array.newInstance(mirror(), 0).getClass());
160 }
161 return arrayOfType;
162 }
163
164 @Override
165 public ResolvedJavaType getComponentType() {
166 Class<?> javaComponentType = mirror().getComponentType();
167 return javaComponentType == null ? null : runtime().fromClass(javaComponentType);
168 }
169
170 @Override
171 public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
172 HotSpotVMConfig config = config();
173 if (isArray()) {
174 return getElementalType().isLeaf() ? new AssumptionResult<>(this) : null;
175 } else if (isInterface()) {
176 HotSpotResolvedObjectTypeImpl implementor = getSingleImplementor();
177 /*
178 * If the implementor field contains itself that indicates that the interface has more
179 * than one implementors (see: InstanceKlass::add_implementor).
180 */
181 if (implementor == null || implementor.equals(this)) {
182 return null;
183 }
184
185 assert !implementor.isInterface();
186 if (implementor.isAbstract() || !implementor.isLeafClass()) {
187 AssumptionResult<ResolvedJavaType> leafConcreteSubtype = implementor.findLeafConcreteSubtype();
188 if (leafConcreteSubtype != null) {
189 assert !leafConcreteSubtype.getResult().equals(implementor);
190 AssumptionResult<ResolvedJavaType> newResult = new AssumptionResult<>(leafConcreteSubtype.getResult(), new ConcreteSubtype(this, implementor));
191 // Accumulate leaf assumptions and return the combined result.
192 newResult.add(leafConcreteSubtype);
217 }
218 }
219
220 /**
221 * Returns if type {@code type} is a leaf class. This is the case if the
222 * {@code Klass::_subklass} field of the underlying class is zero.
223 *
224 * @return true if the type is a leaf class
225 */
226 private boolean isLeafClass() {
227 return getSubklass() == null;
228 }
229
230 /**
231 * Returns the {@code Klass::_subklass} field of the underlying metaspace klass for the given
232 * type {@code type}.
233 *
234 * @return value of the subklass field as metaspace klass pointer
235 */
236 private HotSpotResolvedObjectTypeImpl getSubklass() {
237 return compilerToVM().getResolvedJavaType(this, config().subklassOffset, false);
238 }
239
240 @Override
241 public HotSpotResolvedObjectTypeImpl getSuperclass() {
242 Class<?> javaSuperclass = mirror().getSuperclass();
243 return javaSuperclass == null ? null : fromObjectClass(javaSuperclass);
244 }
245
246 @Override
247 public HotSpotResolvedObjectTypeImpl[] getInterfaces() {
248 if (interfaces == null) {
249 Class<?>[] javaInterfaces = mirror().getInterfaces();
250 HotSpotResolvedObjectTypeImpl[] result = new HotSpotResolvedObjectTypeImpl[javaInterfaces.length];
251 for (int i = 0; i < javaInterfaces.length; i++) {
252 result[i] = fromObjectClass(javaInterfaces[i]);
253 }
254 interfaces = result;
255 }
256 return interfaces;
257 }
258
259 @Override
260 public HotSpotResolvedObjectTypeImpl getSingleImplementor() {
261 if (!isInterface()) {
262 throw new JVMCIError("Cannot call getSingleImplementor() on a non-interface type: %s", this);
263 }
264 return compilerToVM().getImplementor(this);
265 }
266
267 public HotSpotResolvedObjectTypeImpl getSupertype() {
268 if (isArray()) {
269 ResolvedJavaType componentType = getComponentType();
270 if (mirror() == Object[].class || componentType.isPrimitive()) {
271 return fromObjectClass(Object.class);
272 }
273 return (HotSpotResolvedObjectTypeImpl) ((HotSpotResolvedObjectTypeImpl) componentType).getSupertype().getArrayClass();
274 }
275 if (isInterface()) {
276 return fromObjectClass(Object.class);
277 }
278 return getSuperclass();
279 }
280
281 @Override
282 public HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType) {
283 if (otherType.isPrimitive()) {
284 return null;
292 if (t2.isAssignableFrom(t1)) {
293 return t2;
294 }
295 t1 = t1.getSupertype();
296 t2 = t2.getSupertype();
297 }
298 }
299 }
300
301 @Override
302 public HotSpotResolvedObjectType asExactType() {
303 return isLeaf() ? this : null;
304 }
305
306 @Override
307 public JavaConstant getJavaClass() {
308 return HotSpotObjectConstantImpl.forObject(mirror());
309 }
310
311 @Override
312 public Constant getObjectHub() {
313 return klass();
314 }
315
316 @Override
317 public AssumptionResult<Boolean> hasFinalizableSubclass() {
318 assert !isArray();
319 if (!compilerToVM().hasFinalizableSubclass(this)) {
320 return new AssumptionResult<>(false, new NoFinalizableSubclass(this));
321 }
322 return new AssumptionResult<>(true);
323 }
324
325 @Override
326 public boolean hasFinalizer() {
327 HotSpotVMConfig config = config();
328 return (getAccessFlags() & config.klassHasFinalizerFlag) != 0;
329 }
330
331 @Override
332 public boolean isPrimitive() {
333 return false;
334 }
335
336 @Override
337 public boolean isArray() {
338 return mirror().isArray();
339 }
340
341 @Override
342 public boolean isInitialized() {
343 return isArray() ? true : getInitState() == config().instanceKlassStateFullyInitialized;
344 }
345
346 @Override
347 public boolean isLinked() {
348 return isArray() ? true : getInitState() >= config().instanceKlassStateLinked;
349 }
350
351 /**
352 * Returns the value of the state field {@code InstanceKlass::_init_state} of the metaspace
353 * klass.
354 *
355 * @return state field value of this type
356 */
357 private int getInitState() {
358 assert !isArray() : "_init_state only exists in InstanceKlass";
359 return UNSAFE.getByte(getMetaspaceKlass() + config().instanceKlassInitStateOffset) & 0xFF;
360 }
361
362 @Override
363 public void initialize() {
364 if (!isInitialized()) {
365 UNSAFE.ensureClassInitialized(mirror());
366 assert isInitialized();
367 }
368 }
369
370 @Override
371 public boolean isInstance(JavaConstant obj) {
372 if (obj.getJavaKind() == JavaKind.Object && !obj.isNull()) {
373 return mirror().isInstance(((HotSpotObjectConstantImpl) obj).object());
374 }
375 return false;
376 }
377
378 @Override
379 public boolean isInstanceClass() {
408 @Override
409 public ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
410 ResolvedJavaMethod resolvedMethod = resolveMethod(method, callerType);
411 if (resolvedMethod == null || resolvedMethod.isAbstract()) {
412 return null;
413 }
414 return resolvedMethod;
415 }
416
417 @Override
418 public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
419 assert !callerType.isArray();
420 if (method.isConcrete() && method.getDeclaringClass().equals(this) && method.isPublic()) {
421 return method;
422 }
423 if (!method.getDeclaringClass().isAssignableFrom(this)) {
424 return null;
425 }
426 HotSpotResolvedJavaMethodImpl hotSpotMethod = (HotSpotResolvedJavaMethodImpl) method;
427 HotSpotResolvedObjectTypeImpl hotSpotCallerType = (HotSpotResolvedObjectTypeImpl) callerType;
428 return compilerToVM().resolveMethod(this, hotSpotMethod, hotSpotCallerType);
429 }
430
431 public HotSpotConstantPool getConstantPool() {
432 if (constantPool == null) {
433 constantPool = compilerToVM().getConstantPool(this, config().instanceKlassConstantsOffset);
434 }
435 return constantPool;
436 }
437
438 /**
439 * Gets the instance size of this type. If an instance of this type cannot be fast path
440 * allocated, then the returned value is negative (its absolute value gives the size). Must not
441 * be called if this is an array or interface type.
442 */
443 public int instanceSize() {
444 assert !isArray();
445 assert !isInterface();
446
447 HotSpotVMConfig config = config();
448 final int layoutHelper = layoutHelper();
449 assert layoutHelper > config.klassLayoutHelperNeutralValue : "must be instance";
450
451 // See: Klass::layout_helper_size_in_bytes
452 int size = layoutHelper & ~config.klassLayoutHelperInstanceSlowPathBit;
453
454 // See: Klass::layout_helper_needs_slow_path
455 boolean needsSlowPath = (layoutHelper & config.klassLayoutHelperInstanceSlowPathBit) != 0;
456
457 return needsSlowPath ? -size : size;
458 }
459
460 public int layoutHelper() {
461 HotSpotVMConfig config = config();
462 return UNSAFE.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
463 }
464
465 synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
466 HotSpotResolvedJavaMethodImpl method = null;
467 if (methodCache == null) {
468 methodCache = new HashMap<>(8);
469 } else {
470 method = methodCache.get(metaspaceMethod);
471 }
472 if (method == null) {
473 method = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
474 methodCache.put(metaspaceMethod, method);
475 context.add(method);
476 }
477 return method;
478 }
479
480 public int getVtableLength() {
481 HotSpotVMConfig config = config();
482 if (isInterface() || isArray()) {
483 /* Everything has the core vtable of java.lang.Object */
484 return config.baseVtableLength();
485 }
486 int result = UNSAFE.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) / (config.vtableEntrySize / config.heapWordSize);
487 assert result >= config.baseVtableLength() : UNSAFE.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) + " " + config.vtableEntrySize;
488 return result;
489 }
490
491 public synchronized HotSpotResolvedJavaField createField(String fieldName, JavaType type, long offset, int rawFlags) {
492 HotSpotResolvedJavaField result = null;
493
494 final int flags = rawFlags & ModifiersProvider.jvmFieldModifiers();
495
496 final long id = offset + ((long) flags << 32);
497
498 // Must cache the fields, because the local load elimination only works if the
499 // objects from two field lookups are identical.
500 if (fieldCache == null) {
501 fieldCache = new HashMap<>(8);
550 }
551 return null;
552 }
553
554 /**
555 * This class represents the field information for one field contained in the fields array of an
556 * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
557 */
558 private class FieldInfo {
559 /**
560 * Native pointer into the array of Java shorts.
561 */
562 private final long metaspaceData;
563
564 /**
565 * Creates a field info for the field in the fields array at index {@code index}.
566 *
567 * @param index index to the fields array
568 */
569 public FieldInfo(int index) {
570 HotSpotVMConfig config = config();
571 // Get Klass::_fields
572 final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
573 assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code";
574 metaspaceData = metaspaceFields + config.arrayU2DataOffset + config.fieldInfoFieldSlots * Short.BYTES * index;
575 }
576
577 private int getAccessFlags() {
578 return readFieldSlot(config().fieldInfoAccessFlagsOffset);
579 }
580
581 private int getNameIndex() {
582 return readFieldSlot(config().fieldInfoNameIndexOffset);
583 }
584
585 private int getSignatureIndex() {
586 return readFieldSlot(config().fieldInfoSignatureIndexOffset);
587 }
588
589 public int getOffset() {
590 HotSpotVMConfig config = config();
591 final int lowPacked = readFieldSlot(config.fieldInfoLowPackedOffset);
592 final int highPacked = readFieldSlot(config.fieldInfoHighPackedOffset);
593 final int offset = ((highPacked << Short.SIZE) | lowPacked) >> config.fieldInfoTagSize;
594 return offset;
595 }
596
597 /**
598 * Helper method to read an entry (slot) from the field array. Currently field info is laid
599 * on top an array of Java shorts.
600 */
601 private int readFieldSlot(int index) {
602 return UNSAFE.getChar(metaspaceData + Short.BYTES * index);
603 }
604
605 /**
606 * Returns the name of this field as a {@link String}. If the field is an internal field the
607 * name index is pointing into the vmSymbols table.
608 */
609 public String getName() {
610 final int nameIndex = getNameIndex();
611 return isInternal() ? HotSpotVmSymbols.symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex);
612 }
613
614 /**
615 * Returns the signature of this field as {@link String}. If the field is an internal field
616 * the signature index is pointing into the vmSymbols table.
617 */
618 public String getSignature() {
619 final int signatureIndex = getSignatureIndex();
620 return isInternal() ? HotSpotVmSymbols.symbolAt(signatureIndex) : getConstantPool().lookupUtf8(signatureIndex);
621 }
622
623 public JavaType getType() {
624 String signature = getSignature();
625 return runtime().lookupType(signature, HotSpotResolvedObjectTypeImpl.this, false);
626 }
627
628 private boolean isInternal() {
629 return (getAccessFlags() & config().jvmAccFieldInternal) != 0;
630 }
631
632 public boolean isStatic() {
633 return Modifier.isStatic(getAccessFlags());
634 }
635
636 public boolean hasGenericSignature() {
637 return (getAccessFlags() & config().jvmAccFieldHasGenericSignature) != 0;
638 }
639 }
640
641 private static class OffsetComparator implements java.util.Comparator<HotSpotResolvedJavaField> {
642 @Override
643 public int compare(HotSpotResolvedJavaField o1, HotSpotResolvedJavaField o2) {
644 return o1.offset() - o2.offset();
645 }
646 }
647
648 @Override
649 public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
650 if (instanceFields == null) {
651 if (isArray() || isInterface()) {
652 instanceFields = new HotSpotResolvedJavaField[0];
653 } else {
654 final int fieldCount = getFieldCount();
655 ArrayList<HotSpotResolvedJavaField> fieldsArray = new ArrayList<>(fieldCount);
656
657 for (int i = 0; i < fieldCount; i++) {
710 // We are only interested in static fields.
711 if (field.isStatic()) {
712 HotSpotResolvedJavaField resolvedJavaField = createField(field.getName(), field.getType(), field.getOffset(), field.getAccessFlags());
713 fieldsArray.add(resolvedJavaField);
714 }
715 }
716
717 fieldsArray.sort(new OffsetComparator());
718 return fieldsArray.toArray(new HotSpotResolvedJavaField[fieldsArray.size()]);
719 }
720 }
721
722 /**
723 * Returns the actual field count of this class's internal {@code InstanceKlass::_fields} array
724 * by walking the array and discounting the generic signature slots at the end of the array.
725 *
726 * <p>
727 * See {@code FieldStreamBase::init_generic_signature_start_slot}
728 */
729 private int getFieldCount() {
730 HotSpotVMConfig config = config();
731 final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
732 int metaspaceFieldsLength = UNSAFE.getInt(metaspaceFields + config.arrayU1LengthOffset);
733 int fieldCount = 0;
734
735 for (int i = 0, index = 0; i < metaspaceFieldsLength; i += config.fieldInfoFieldSlots, index++) {
736 FieldInfo field = new FieldInfo(index);
737 if (field.hasGenericSignature()) {
738 metaspaceFieldsLength--;
739 }
740 fieldCount++;
741 }
742 return fieldCount;
743 }
744
745 @Override
746 public Class<?> mirror() {
747 return javaClass;
748 }
749
750 @Override
751 public String getSourceFileName() {
752 HotSpotVMConfig config = config();
753 final int sourceFileNameIndex = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassSourceFileNameIndexOffset);
754 if (sourceFileNameIndex == 0) {
755 return null;
756 }
757 return getConstantPool().lookupUtf8(sourceFileNameIndex);
758 }
759
760 @Override
761 public Annotation[] getAnnotations() {
762 return mirror().getAnnotations();
763 }
764
765 @Override
766 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
767 return mirror().getAnnotation(annotationClass);
768 }
769
770 /**
771 * Performs a fast-path check that this type is resolved in the context of a given accessing
772 * class. A negative result does not mean this type is not resolved with respect to
787 assert mirror().getClassLoader() == null;
788 return true;
789 }
790 ClassLoader thisCl = mirror().getClassLoader();
791 ClassLoader accessingClassCl = ((HotSpotResolvedObjectTypeImpl) accessingClass).mirror().getClassLoader();
792 return thisCl == accessingClassCl;
793 }
794
795 @Override
796 public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
797 if (isDefinitelyResolvedWithRespectTo(requireNonNull(accessingClass))) {
798 return this;
799 }
800 HotSpotResolvedObjectTypeImpl accessingType = (HotSpotResolvedObjectTypeImpl) accessingClass;
801 return (ResolvedJavaType) runtime().lookupType(getName(), accessingType, true);
802 }
803
804 /**
805 * Gets the metaspace Klass boxed in a {@link JavaConstant}.
806 */
807 public Constant klass() {
808 return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false);
809 }
810
811 public boolean isPrimaryType() {
812 return config().secondarySuperCacheOffset != superCheckOffset();
813 }
814
815 public int superCheckOffset() {
816 HotSpotVMConfig config = config();
817 return UNSAFE.getInt(getMetaspaceKlass() + config.superCheckOffsetOffset);
818 }
819
820 public long prototypeMarkWord() {
821 HotSpotVMConfig config = config();
822 if (isArray()) {
823 return config.arrayPrototypeMarkWord();
824 } else {
825 return UNSAFE.getAddress(getMetaspaceKlass() + config.prototypeMarkWordOffset);
826 }
827 }
828
829 @Override
830 public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedEntryKind) {
831 ResolvedJavaField[] declaredFields = getInstanceFields(true);
832 for (ResolvedJavaField field : declaredFields) {
833 HotSpotResolvedJavaField resolvedField = (HotSpotResolvedJavaField) field;
834 long resolvedFieldOffset = resolvedField.offset();
835 // @formatter:off
836 if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN &&
837 expectedEntryKind.isPrimitive() &&
838 !expectedEntryKind.equals(JavaKind.Void) &&
839 resolvedField.getJavaKind().isPrimitive()) {
840 resolvedFieldOffset +=
841 resolvedField.getJavaKind().getByteCount() -
877 ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length];
878 for (int i = 0; i < constructors.length; i++) {
879 result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(constructors[i]);
880 assert result[i].isConstructor();
881 }
882 return result;
883 }
884
885 @Override
886 public ResolvedJavaMethod[] getDeclaredMethods() {
887 Method[] methods = mirror().getDeclaredMethods();
888 ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length];
889 for (int i = 0; i < methods.length; i++) {
890 result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(methods[i]);
891 assert !result[i].isConstructor();
892 }
893 return result;
894 }
895
896 public ResolvedJavaMethod getClassInitializer() {
897 return compilerToVM().getClassInitializer(this);
898 }
899
900 @Override
901 public String toString() {
902 return "HotSpotType<" + getName() + ", resolved>";
903 }
904
905 @Override
906 public boolean isTrustedInterfaceType() {
907 return TrustedInterface.class.isAssignableFrom(mirror());
908 }
909 }
|