From c9cfe1957924da708e4e84fcaa724628eb65dff1 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Tue, 10 Dec 2024 20:43:54 +0100 Subject: [PATCH 1/4] Move non-critical DynamicHub fields to companion object. --- .../core/graal/meta/DynamicHubOffsets.java | 98 ------ .../com/oracle/svm/core/hub/DynamicHub.java | 329 +++++++----------- .../svm/core/hub/DynamicHubCompanion.java | 105 +++++- .../src/com/oracle/svm/hosted/SVMHost.java | 6 +- .../analysis/DynamicHubInitializer.java | 25 +- .../imagelayer/SVMImageLayerLoader.java | 28 +- .../imagelayer/SVMImageLayerSnapshotUtil.java | 34 +- 7 files changed, 290 insertions(+), 335 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/DynamicHubOffsets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/DynamicHubOffsets.java index 479b6c8b41b9..4d6788357b2f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/DynamicHubOffsets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/DynamicHubOffsets.java @@ -75,54 +75,20 @@ public class DynamicHubOffsets { @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // private int flagsOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int additionalFlagsOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int modifiersOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int superHubOffset; @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // private int componentTypeOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int arrayHubOffset; - - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int declaringClassOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int interfacesEncodingOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int enumConstantsReferenceOffset; @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // private int referenceMapIndexOffset; @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // private int layerIdOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int metaTypeOffset; - - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int sourceFileNameOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int classInitializationInfoOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int moduleOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int nestHostOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int simpleBinaryNameOffset; @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // private int companionOffset; @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // private int signatureOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int classRedefinedCountOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int hubMetadataOffset; - @UnknownPrimitiveField(availability = BuildPhaseProvider.ReadyForCompilation.class) // - private int reflectionMetadataOffset; @Fold public static DynamicHubOffsets singleton() { @@ -205,38 +171,10 @@ public int getFlagsOffset() { return flagsOffset; } - public int getAdditionalFlagsOffset() { - return additionalFlagsOffset; - } - - public int getModifiersOffset() { - return modifiersOffset; - } - - public int getSuperHubOffset() { - return superHubOffset; - } - public int getComponentTypeOffset() { return componentTypeOffset; } - public int getArrayHubOffset() { - return arrayHubOffset; - } - - public int getDeclaringClassOffset() { - return declaringClassOffset; - } - - public int getInterfacesEncodingOffset() { - return interfacesEncodingOffset; - } - - public int getEnumConstantsReferenceOffset() { - return enumConstantsReferenceOffset; - } - public int getReferenceMapIndexOffset() { return referenceMapIndexOffset; } @@ -245,30 +183,6 @@ public int getLayerIdOffset() { return layerIdOffset; } - public int getMetaTypeOffset() { - return metaTypeOffset; - } - - public int getSourceFileNameOffset() { - return sourceFileNameOffset; - } - - public int getClassInitializationInfoOffset() { - return classInitializationInfoOffset; - } - - public int getModuleOffset() { - return moduleOffset; - } - - public int getNestHostOffset() { - return nestHostOffset; - } - - public int getSimpleBinaryNameOffset() { - return simpleBinaryNameOffset; - } - public int getCompanionOffset() { return companionOffset; } @@ -277,18 +191,6 @@ public int getSignatureOffset() { return signatureOffset; } - public int getClassRedefinedCountOffset() { - return classRedefinedCountOffset; - } - - public int getHubMetadataOffset() { - return hubMetadataOffset; - } - - public int getReflectionMetadataOffset() { - return reflectionMetadataOffset; - } - public static void writeObject(DynamicHub hub, int offset, Object value) { if (offset < 0) { /* field removed by analysis */ diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java index b987d124633b..1c0ac3bab6e3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java @@ -87,7 +87,6 @@ import org.graalvm.nativeimage.c.function.CFunctionPointer; import org.graalvm.nativeimage.impl.InternalPlatform; -import com.oracle.svm.core.BuildPhaseProvider.AfterCompilation; import com.oracle.svm.core.BuildPhaseProvider.AfterHostedUniverse; import com.oracle.svm.core.BuildPhaseProvider.CompileQueueFinished; import com.oracle.svm.core.NeverInline; @@ -143,18 +142,24 @@ import jdk.internal.reflect.FieldAccessor; import jdk.internal.reflect.Reflection; import jdk.internal.reflect.ReflectionFactory; -import jdk.internal.vm.annotation.Stable; import sun.reflect.annotation.AnnotationType; import sun.reflect.generics.factory.GenericsFactory; import sun.reflect.generics.repository.ClassRepository; /** - * Instantiations of this class have a special layout. See {@code DynamicHubLayout} for a - * description of how the object is arranged. + * Information on a single type. + *

+ * Instances of this class that use relocations (for the vtable) reside in a special partition of + * the image heap in read-only memory. That partition incurs extra initialization and memory + * overhead. Therefore, this class should contain only data critical for performance (type checks, + * vtable, GC information). Other data or data that needs to be mutable must be stored in + * {@link DynamicHubCompanion}. Do not add such fields here. + *

+ * Objects of this class have a special layout. See {@code DynamicHubLayout} for a description of + * how the object is arranged. *

- * A {@code DynamicHub} ends up initialized in the read-only part of the image heap, and therefore - * fields are considered immutable. In scenarios where a {@code DynamicHub} can be allocated at - * run-time it is important to keep this property. + * In scenarios where a {@code DynamicHub} can be allocated at run-time, it must remain immutable + * and fixed to its initial address. */ @Substitute @TargetClass(java.lang.Class.class) @@ -323,26 +328,8 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ */ private static final int IS_PROXY_CLASS_BIT = 11; - /** - * Similar to {@link #flags}, but non-final because {@link #setSharedData} sets the value. - */ - @UnknownPrimitiveField(availability = AfterHostedUniverse.class)// - private byte additionalFlags; - /** Indicates whether the type has been discovered as instantiated by the static analysis. */ - private static final int IS_INSTANTIATED_BIT = 0; - - /** - * The {@link Modifier modifiers} of this class. - */ - private final int modifiers; - - /** - * The hub for the superclass, or null if an interface or primitive type. - * - * @see Class#getSuperclass() - */ - private final DynamicHub superHub; + private static final int ADDITIONAL_FLAGS_INSTANTIATED_BIT = 0; /** * The hub for the component type of an array, or null if this hub is not an array hub. @@ -352,29 +339,6 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ @Substitute // private final DynamicHub componentType; - /** - * The hub for an array of this type, or null if the array type has been determined as - * uninstantiated by the static analysis. - */ - private DynamicHub arrayHub; - - /** - * The class that declares this class, as returned by {@code Class.getDeclaringClass0} or an - * exception that happened at image-build time. - */ - private final Object declaringClass; - - /** - * The interfaces that this class implements. Either null (no interfaces), a {@link DynamicHub} - * (one interface), or a {@link DynamicHub}[] array (more than one interface). - */ - private Object interfacesEncoding; - - /** - * Reference to a list of enum values for subclasses of {@link Enum}; null otherwise. - */ - private Object enumConstantsReference; - /** * Reference map information for this hub. The byte[] array encoding data is available via * {@link DynamicHubSupport#getReferenceMapEncoding()}. @@ -384,43 +348,11 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ private final byte layerId; - /** - * Back link to the SubstrateType used by the substrate meta access. Only used for the subset of - * types for which a SubstrateType exists. - */ - @UnknownObjectField(fullyQualifiedTypes = "com.oracle.svm.graal.meta.SubstrateType", canBeNull = true)// - private SharedType metaType; - - /** - * Source file name if known; null otherwise. - */ - private final String sourceFileName; - - /** - * Metadata for running class initializers at run time. Refers to a singleton marker object for - * classes/interfaces already initialized during image generation, i.e., this field is never - * null at run time. - */ - @Stable // - private ClassInitializationInfo classInitializationInfo; - @UnknownObjectField(availability = AfterHostedUniverse.class)// private CFunctionPointer[] vtable; - /** Field used for module information access at run-time. */ - @Stable // - private Module module; - - /** The class that serves as the host for the nest. All nestmates have the same host. */ - private final Class nestHost; - - /** The simple binary name of this class, as returned by {@code Class.getSimpleBinaryName0}. */ - private final String simpleBinaryName; - private final DynamicHubCompanion companion; - private final String signature; - @Substitute // @InjectAccessors(ClassLoaderAccessors.class) // private ClassLoader classLoader; @@ -430,7 +362,7 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ private SoftReference> reflectionData; @Substitute // - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) // + @InjectAccessors(ClassRedefinedCountAccessors.class) // private int classRedefinedCount; @Substitute // @@ -448,36 +380,23 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ @InjectAccessors(CachedConstructorAccessors.class) // private Constructor cachedConstructor; - @UnknownObjectField(canBeNull = true, availability = AfterCompilation.class) // - private DynamicHubMetadata hubMetadata; - - @UnknownObjectField(canBeNull = true, availability = AfterCompilation.class) // - private ReflectionMetadata reflectionMetadata; - @Platforms(Platform.HOSTED_ONLY.class) public DynamicHub(Class hostedJavaClass, String name, byte hubType, ReferenceType referenceType, DynamicHub superType, DynamicHub componentHub, String sourceFileName, int modifiers, short flags, ClassLoader classLoader, Class nestHost, String simpleBinaryName, Object declaringClass, String signature, int layerId) { this.hostedJavaClass = hostedJavaClass; - this.module = hostedJavaClass.getModule(); this.name = name; this.hubType = hubType; this.referenceType = referenceType.getValue(); - this.superHub = superType; this.componentType = componentHub; - this.sourceFileName = sourceFileName; - this.modifiers = modifiers; - this.nestHost = nestHost; - this.simpleBinaryName = simpleBinaryName; - this.declaringClass = declaringClass; - this.signature = signature; assert layerId < DynamicImageLayerInfo.CREMA_LAYER_ID; this.layerId = NumUtil.safeToByte(layerId); this.flags = flags; - this.companion = new DynamicHubCompanion(hostedJavaClass, classLoader); + this.companion = new DynamicHubCompanion(hostedJavaClass, hostedJavaClass.getModule(), superType, sourceFileName, + modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature); } /** @@ -503,15 +422,22 @@ public static DynamicHub allocate(String name, DynamicHub superHub, DynamicHub c ReferenceType referenceType = ReferenceType.computeReferenceType(DynamicHub.toClass(superHub)); // GR-59683: HubType.OBJECT_ARRAY? - byte hubType = (byte) ((referenceType == ReferenceType.None) ? HubType.INSTANCE : HubType.REFERENCE_INSTANCE); + byte hubType = HubType.INSTANCE; + if (referenceType != ReferenceType.None) { + hubType = HubType.REFERENCE_INSTANCE; + } + + // GR-59683 + Module module = null; + + DynamicHubCompanion companion = new DynamicHubCompanion(classLoader, module, superHub, sourceFileName, modifiers, nestHost, simpleBinaryName, declaringClass, signature); - DynamicHubCompanion companion = new DynamicHubCompanion(classLoader); /* Always allow unsafe allocation for classes that were loaded at run-time. */ companion.setUnsafeAllocate(); // GR-59687: Correct size and content for vtable int vTableEntries = 0x100; - ClassInitializationInfo classInitializationInfo = new ClassInitializationInfo(false); + companion.classInitializationInfo = new ClassInitializationInfo(false); // GR-60069: Determine size for instance and offsets for monitor and identityHashCode int layoutEncoding = 0x40; @@ -525,26 +451,29 @@ public static DynamicHub allocate(String name, DynamicHub superHub, DynamicHub c short numInterfacesTypes = 0; int[] openTypeWorldTypeCheckSlots = new int[numClassTypes + (numInterfacesTypes * 2)]; - byte additionalFlags = NumUtil.safeToUByte(makeFlag(IS_INSTANTIATED_BIT, true)); - // GR-59683: Proper values needed. - DynamicHub arrayHub = null; - Object interfacesEncoding = null; - Object enumConstantsReference = null; + companion.interfacesEncoding = null; + companion.enumConstantsReference = null; + + /* + * These are read in snippets and must also not be set directly or the analysis would not + * consider them to be immutable: + * + * companion.arrayHub = null; + * + * companion.additionalFlags = + * NumUtil.safeToUByte(makeFlag(ADDITIONAL_FLAGS_INSTANTIATED_BIT, true)); + */ // GR-60080: Proper referenceMap needed. int referenceMapIndex = DynamicHub.fromClass(Object.class).referenceMapIndex; // GR-59683: Maybe can be used to inject a backreference to InterpreterResolvedObjectType - SharedType metaType = null; - - // GR-59683 - Module module = null; + companion.metaType = null; // GR-57813 - int classRedefinedCount = 0; - DynamicHubMetadata hubMetadata = null; - ReflectionMetadata reflectionMetadata = null; + companion.hubMetadata = null; + companion.reflectionMetadata = null; /* * We cannot do the allocation via {@code new DynamicHub(...)} because we need to inject the @@ -572,34 +501,17 @@ public static DynamicHub allocate(String name, DynamicHub superHub, DynamicHub c writeChar(hub, dynamicHubOffsets.getIdentityHashOffsetOffset(), identityHashOffset); writeShort(hub, dynamicHubOffsets.getFlagsOffset(), flags); - writeByte(hub, dynamicHubOffsets.getAdditionalFlagsOffset(), additionalFlags); - writeInt(hub, dynamicHubOffsets.getModifiersOffset(), modifiers); - writeObject(hub, dynamicHubOffsets.getSuperHubOffset(), superHub); writeObject(hub, dynamicHubOffsets.getComponentTypeOffset(), componentHub); - writeObject(hub, dynamicHubOffsets.getArrayHubOffset(), arrayHub); - - writeObject(hub, dynamicHubOffsets.getDeclaringClassOffset(), declaringClass); - writeObject(hub, dynamicHubOffsets.getInterfacesEncodingOffset(), interfacesEncoding); - writeObject(hub, dynamicHubOffsets.getEnumConstantsReferenceOffset(), enumConstantsReference); writeInt(hub, dynamicHubOffsets.getReferenceMapIndexOffset(), referenceMapIndex); writeByte(hub, dynamicHubOffsets.getLayerIdOffset(), NumUtil.safeToByte(DynamicImageLayerInfo.CREMA_LAYER_ID)); - writeObject(hub, dynamicHubOffsets.getMetaTypeOffset(), metaType); - writeObject(hub, dynamicHubOffsets.getSourceFileNameOffset(), sourceFileName); - writeObject(hub, dynamicHubOffsets.getClassInitializationInfoOffset(), classInitializationInfo); // skip vtable (special treatment) - writeObject(hub, dynamicHubOffsets.getModuleOffset(), module); - writeObject(hub, dynamicHubOffsets.getNestHostOffset(), nestHost); - writeObject(hub, dynamicHubOffsets.getSimpleBinaryNameOffset(), simpleBinaryName); writeObject(hub, dynamicHubOffsets.getCompanionOffset(), companion); writeObject(hub, dynamicHubOffsets.getSignatureOffset(), signature); - writeInt(hub, dynamicHubOffsets.getClassRedefinedCountOffset(), classRedefinedCount); - writeObject(hub, dynamicHubOffsets.getHubMetadataOffset(), hubMetadata); - writeObject(hub, dynamicHubOffsets.getReflectionMetadataOffset(), reflectionMetadata); FinalFieldBarrierNode.finalFieldBarrier(hub); @@ -641,8 +553,9 @@ private static boolean isFlagSet(short flags, int flagBit) { @Platforms(Platform.HOSTED_ONLY.class) public void setClassInitializationInfo(ClassInitializationInfo classInitializationInfo) { + assert companion.classInitializationInfo == null; assert classInitializationInfo != null; - this.classInitializationInfo = classInitializationInfo; + companion.classInitializationInfo = classInitializationInfo; } @Platforms(Platform.HOSTED_ONLY.class) @@ -659,7 +572,9 @@ public void setSharedData(int layoutEncoding, int monitorOffset, int identityHas throw VMError.shouldNotReachHere("Reference map index not within integer range, need to switch field from int to long"); } this.referenceMapIndex = (int) referenceMapIndex; - this.additionalFlags = NumUtil.safeToUByte(makeFlag(IS_INSTANTIATED_BIT, isInstantiated)); + + assert companion.additionalFlags == 0; + companion.additionalFlags = NumUtil.safeToUByte(makeFlag(ADDITIONAL_FLAGS_INSTANTIATED_BIT, isInstantiated)); } @Platforms(Platform.HOSTED_ONLY.class) @@ -689,69 +604,82 @@ public void setOpenTypeWorldData(CFunctionPointer[] vtable, int typeID, @Platforms(Platform.HOSTED_ONLY.class) public void setArrayHub(DynamicHub arrayHub) { - assert (this.arrayHub == null || this.arrayHub == arrayHub) && arrayHub != null; + assert (companion.arrayHub == null || companion.arrayHub == arrayHub) && arrayHub != null; assert arrayHub.getComponentHub() == this; - this.arrayHub = arrayHub; + companion.arrayHub = arrayHub; } @Platforms(Platform.HOSTED_ONLY.class) public void setInterfacesEncoding(Object interfacesEncoding) { - this.interfacesEncoding = interfacesEncoding; + assert companion.interfacesEncoding == null; + companion.interfacesEncoding = interfacesEncoding; } @Platforms(Platform.HOSTED_ONLY.class) public Object getInterfacesEncoding() { - return interfacesEncoding; + return companion.interfacesEncoding; } @Platforms(Platform.HOSTED_ONLY.class) public boolean shouldInitEnumConstants() { - return enumConstantsReference == null; + return companion.enumConstantsReference == null; } @Platforms(Platform.HOSTED_ONLY.class) public void initEnumConstants(Enum[] enumConstants) { + assert companion.enumConstantsReference == null; /* Enum is eagerly initialized, so no need for `LazyFinalReference`. */ - enumConstantsReference = enumConstants; + companion.enumConstantsReference = enumConstants; } @Platforms(Platform.HOSTED_ONLY.class) public void initEnumConstantsAtRuntime(Class enumClass) { + assert companion.enumConstantsReference == null; /* Adapted from `Class.getEnumConstantsShared`. */ try { Method values = ReflectionUtil.lookupMethod(enumClass, "values"); - enumConstantsReference = new LazyFinalReference<>(() -> initEnumConstantsAtRuntime(values)); + companion.enumConstantsReference = new LazyFinalReference<>(() -> initEnumConstantsAtRuntime(values)); } catch (ReflectionUtilError e) { /* * This can happen when users concoct enum-like classes that don't comply with the enum * spec. */ - enumConstantsReference = null; + companion.enumConstantsReference = null; } catch (NoClassDefFoundError e) { /* * This can happen when an enum references a missing class. So, in order to match the * JVM behaviour, we rethrow the error at runtime. */ String message = e.getMessage(); - enumConstantsReference = new LazyFinalReference<>(() -> throwNoClassDefFoundErrorAtRuntime(message)); + companion.enumConstantsReference = new LazyFinalReference<>(() -> throwNoClassDefFoundErrorAtRuntime(message)); } } @Platforms(Platform.HOSTED_ONLY.class) public String getSignature() { - return signature; + return companion.signature; } @Platforms(Platform.HOSTED_ONLY.class) public void setHubMetadata(int enclosingMethodInfoIndex, int annotationsIndex, int typeAnnotationsIndex, int classesEncodingIndex, int permittedSubclassesEncodingIndex, int nestMembersEncodingIndex, int signersEncodingIndex) { - this.hubMetadata = new DynamicHubMetadata(enclosingMethodInfoIndex, annotationsIndex, typeAnnotationsIndex, classesEncodingIndex, permittedSubclassesEncodingIndex, nestMembersEncodingIndex, - signersEncodingIndex); + assert companion.hubMetadata == null; + companion.hubMetadata = new DynamicHubMetadata(enclosingMethodInfoIndex, annotationsIndex, typeAnnotationsIndex, classesEncodingIndex, permittedSubclassesEncodingIndex, + nestMembersEncodingIndex, signersEncodingIndex); + } + + private DynamicHubMetadata hubMetadata() { + return companion.hubMetadata; } @Platforms(Platform.HOSTED_ONLY.class) public void setReflectionMetadata(int fieldsEncodingIndex, int methodsEncodingIndex, int constructorsEncodingIndex, int recordComponentsEncodingIndex, int classFlags) { - this.reflectionMetadata = new ReflectionMetadata(fieldsEncodingIndex, methodsEncodingIndex, constructorsEncodingIndex, recordComponentsEncodingIndex, classFlags); + assert companion.reflectionMetadata == null; + companion.reflectionMetadata = new ReflectionMetadata(fieldsEncodingIndex, methodsEncodingIndex, constructorsEncodingIndex, recordComponentsEncodingIndex, classFlags); + } + + private ReflectionMetadata reflectionMetadata() { + return companion.reflectionMetadata; } private void checkClassFlag(int mask, String methodName) { @@ -761,7 +689,7 @@ private void checkClassFlag(int mask, String methodName) { } private boolean isClassFlagSet(int mask) { - return (reflectionMetadata != null && (reflectionMetadata.classFlags & mask) != 0); + return (reflectionMetadata() != null && (reflectionMetadata().classFlags & mask) != 0); } /** Executed at runtime. */ @@ -784,7 +712,8 @@ private static Object throwNoClassDefFoundErrorAtRuntime(String message) { @Platforms(Platform.HOSTED_ONLY.class) public void setMetaType(SharedType metaType) { - this.metaType = metaType; + assert companion.metaType == null; + companion.metaType = metaType; } public boolean hasDefaultMethods() { @@ -796,11 +725,11 @@ public boolean declaresDefaultMethods() { } public ClassInitializationInfo getClassInitializationInfo() { - return classInitializationInfo; + return companion.classInitializationInfo; } public boolean isInitialized() { - return classInitializationInfo.isInitialized(); + return companion.classInitializationInfo.isInitialized(); } public void ensureInitialized() { @@ -808,12 +737,12 @@ public void ensureInitialized() { } public SharedType getMetaType() { - return metaType; + return companion.metaType; } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public String getSourceFileName() { - return sourceFileName; + return companion.sourceFileName; } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @@ -880,7 +809,7 @@ public int getIdentityHashOffset() { } public DynamicHub getSuperHub() { - return superHub; + return companion.superHub; } public DynamicHub getComponentHub() { @@ -888,7 +817,7 @@ public DynamicHub getComponentHub() { } public DynamicHub getArrayHub() { - return arrayHub; + return companion.arrayHub; } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @@ -907,7 +836,7 @@ public int getLayerId() { } public boolean isInstantiated() { - return isFlagSet(additionalFlags, IS_INSTANTIATED_BIT); + return isFlagSet(companion.additionalFlags, ADDITIONAL_FLAGS_INSTANTIATED_BIT); } public boolean canUnsafeInstantiateAsInstanceFastPath() { @@ -1002,11 +931,11 @@ public boolean isPrimitive() { @Substitute public int getModifiers() { - return modifiers; + return companion.modifiers; } public int getClassAccessFlags() { - return reflectionMetadata != null ? (reflectionMetadata.classFlags & CLASS_ACCESS_FLAGS_MASK) : modifiers; + return reflectionMetadata() != null ? (reflectionMetadata().classFlags & CLASS_ACCESS_FLAGS_MASK) : companion.modifiers; } @Substitute @@ -1016,7 +945,7 @@ private DynamicHub getComponentType() { @Substitute private DynamicHub getSuperclass() { - return superHub; + return companion.superHub; } @Substitute @@ -1057,6 +986,7 @@ private boolean isEnum() { @Substitute public Object[] getEnumConstantsShared() { + Object enumConstantsReference = companion.enumConstantsReference; if (enumConstantsReference instanceof LazyFinalReference) { return (Object[]) ((LazyFinalReference) enumConstantsReference).get(); } @@ -1069,7 +999,7 @@ public Object[] getEnumConstantsShared() { @Substitute public InputStream getResourceAsStream(String resourceName) { String resolvedName = resolveName(resourceName); - return Resources.singleton().createInputStream(module, resolvedName); + return Resources.singleton().createInputStream(companion.module, resolvedName); } @KeepOriginal @@ -1174,6 +1104,7 @@ public boolean isRegisteredForSerialization() { @Substitute private Class getDeclaringClass0() { + Object declaringClass = companion.declaringClass; if (declaringClass == null) { return null; } else if (declaringClass instanceof Class) { @@ -1477,12 +1408,12 @@ public Method getDeclaredMethod(String methodName, Class... parameterTypes) t @Substitute private RecordComponent[] getRecordComponents0() { checkClassFlag(ALL_RECORD_COMPONENTS_FLAG, "getRecordComponents"); - if (reflectionMetadata == null || reflectionMetadata.recordComponentsEncodingIndex == NO_DATA) { + if (reflectionMetadata() == null || reflectionMetadata().recordComponentsEncodingIndex == NO_DATA) { /* See ReflectionDataBuilder.buildRecordComponents() for details. */ throw VMError.unsupportedFeature("Record components not available for record class " + getTypeName() + ". " + "All record component accessor methods of this record class must be included in the reflection configuration at image build time, then this method can be called."); } - return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseRecordComponents(this, reflectionMetadata.recordComponentsEncodingIndex); + return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseRecordComponents(this, reflectionMetadata().recordComponentsEncodingIndex); } @KeepOriginal @@ -1742,10 +1673,10 @@ public Object[] getSigners() { return null; } checkClassFlag(ALL_SIGNERS_FLAG, "getSigners"); - if (hubMetadata == null || hubMetadata.signersEncodingIndex == NO_DATA) { + if (hubMetadata() == null || hubMetadata().signersEncodingIndex == NO_DATA) { return null; } - return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseObjects(hubMetadata.signersEncodingIndex, this); + return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseObjects(hubMetadata().signersEncodingIndex, this); } @Substitute @@ -1769,7 +1700,7 @@ public boolean desiredAssertionStatus() { @Substitute // public Module getModule() { - return module; + return companion.module; } @Substitute // @@ -1795,7 +1726,7 @@ private static String describeMethod(String prefix, Class[] argTypes, String @Substitute // private String getSimpleBinaryName0() { - return simpleBinaryName; + return companion.simpleBinaryName; } /** @@ -1834,12 +1765,12 @@ List getDeclaredPublicMethods(String methodName, Class... parameterTy @Substitute public Class getNestHost() { - return nestHost; + return companion.nestHost; } @Substitute public boolean isNestmateOf(Class c) { - return nestHost == DynamicHub.fromClass(c).nestHost; + return companion.nestHost == DynamicHub.fromClass(c).companion.nestHost; } @KeepOriginal @@ -1857,10 +1788,10 @@ public DynamicHub arrayType() { if (toClass(this) == void.class) { throw new UnsupportedOperationException(new IllegalArgumentException()); } - if (arrayHub == null) { + if (companion.arrayHub == null) { MissingReflectionRegistrationUtils.forClass(getTypeName() + "[]"); } - return arrayHub; + return companion.arrayHub; } @KeepOriginal @@ -1890,10 +1821,10 @@ public DynamicHub arrayType() { @Substitute private Object[] getEnclosingMethod0() { - if (hubMetadata == null || hubMetadata.enclosingMethodInfoIndex == NO_DATA) { + if (hubMetadata() == null || hubMetadata().enclosingMethodInfoIndex == NO_DATA) { return null; } - Object[] enclosingMethod = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseEnclosingMethod(hubMetadata.enclosingMethodInfoIndex, this); + Object[] enclosingMethod = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseEnclosingMethod(hubMetadata().enclosingMethodInfoIndex, this); if (enclosingMethod != null) { PredefinedClassesSupport.throwIfUnresolvable((Class) enclosingMethod[0], getClassLoader0()); } @@ -1902,6 +1833,7 @@ private Object[] getEnclosingMethod0() { @Substitute private DynamicHub[] getInterfaces0() { + Object interfacesEncoding = companion.interfacesEncoding; if (interfacesEncoding == null) { return new DynamicHub[0]; } else if (interfacesEncoding instanceof DynamicHub) { @@ -1921,23 +1853,23 @@ private void setSigners(@SuppressWarnings("unused") Object[] signers) { @Substitute private String getGenericSignature0() { - return signature; + return companion.signature; } @Substitute byte[] getRawAnnotations() { - if (hubMetadata == null || hubMetadata.annotationsIndex == NO_DATA) { + if (hubMetadata() == null || hubMetadata().annotationsIndex == NO_DATA) { return null; } - return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseByteArray(hubMetadata.annotationsIndex, this); + return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseByteArray(hubMetadata().annotationsIndex, this); } @Substitute byte[] getRawTypeAnnotations() { - if (hubMetadata == null || hubMetadata.typeAnnotationsIndex == NO_DATA) { + if (hubMetadata() == null || hubMetadata().typeAnnotationsIndex == NO_DATA) { return null; } - return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseByteArray(hubMetadata.typeAnnotationsIndex, this); + return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseByteArray(hubMetadata().typeAnnotationsIndex, this); } @Substitute @@ -1947,34 +1879,34 @@ Target_jdk_internal_reflect_ConstantPool getConstantPool() { @Substitute private Field[] getDeclaredFields0(boolean publicOnly) { - if (reflectionMetadata == null || reflectionMetadata.fieldsEncodingIndex == NO_DATA) { + if (reflectionMetadata() == null || reflectionMetadata().fieldsEncodingIndex == NO_DATA) { return new Field[0]; } - return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseFields(this, reflectionMetadata.fieldsEncodingIndex, publicOnly); + return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseFields(this, reflectionMetadata().fieldsEncodingIndex, publicOnly); } @Substitute private Method[] getDeclaredMethods0(boolean publicOnly) { - if (reflectionMetadata == null || reflectionMetadata.methodsEncodingIndex == NO_DATA) { + if (reflectionMetadata() == null || reflectionMetadata().methodsEncodingIndex == NO_DATA) { return new Method[0]; } - return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseMethods(this, reflectionMetadata.methodsEncodingIndex, publicOnly); + return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseMethods(this, reflectionMetadata().methodsEncodingIndex, publicOnly); } @Substitute private Constructor[] getDeclaredConstructors0(boolean publicOnly) { - if (reflectionMetadata == null || reflectionMetadata.constructorsEncodingIndex == NO_DATA) { + if (reflectionMetadata() == null || reflectionMetadata().constructorsEncodingIndex == NO_DATA) { return new Constructor[0]; } - return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseConstructors(this, reflectionMetadata.constructorsEncodingIndex, publicOnly); + return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseConstructors(this, reflectionMetadata().constructorsEncodingIndex, publicOnly); } @Substitute private Class[] getDeclaredClasses0() { - if (hubMetadata == null || hubMetadata.classesEncodingIndex == NO_DATA) { + if (hubMetadata() == null || hubMetadata().classesEncodingIndex == NO_DATA) { return new Class[0]; } - Class[] declaredClasses = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata.classesEncodingIndex, this); + Class[] declaredClasses = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata().classesEncodingIndex, this); for (Class clazz : declaredClasses) { PredefinedClassesSupport.throwIfUnresolvable(clazz, getClassLoader0()); } @@ -1990,10 +1922,10 @@ private Class[] getDeclaredClasses0() { @Substitute private Class[] getNestMembers0() { checkClassFlag(ALL_NEST_MEMBERS_FLAG, "getNestMembers"); - if (hubMetadata == null || hubMetadata.nestMembersEncodingIndex == NO_DATA) { + if (hubMetadata() == null || hubMetadata().nestMembersEncodingIndex == NO_DATA) { return new Class[]{DynamicHub.toClass(this)}; } - Class[] nestMembers = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata.nestMembersEncodingIndex, this); + Class[] nestMembers = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata().nestMembersEncodingIndex, this); for (Class clazz : nestMembers) { PredefinedClassesSupport.throwIfUnresolvable(clazz, getClassLoader0()); } @@ -2042,10 +1974,10 @@ private Class[] getPermittedSubclasses0() { return null; } checkClassFlag(ALL_PERMITTED_SUBCLASSES_FLAG, "getPermittedSubclasses"); - if (hubMetadata == null || hubMetadata.permittedSubclassesEncodingIndex == NO_DATA) { + if (hubMetadata() == null || hubMetadata().permittedSubclassesEncodingIndex == NO_DATA) { return new Class[0]; } - Class[] permittedSubclasses = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata.permittedSubclassesEncodingIndex, this); + Class[] permittedSubclasses = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata().permittedSubclassesEncodingIndex, this); for (Class clazz : permittedSubclasses) { PredefinedClassesSupport.throwIfUnresolvable(clazz, getClassLoader0()); } @@ -2137,7 +2069,7 @@ public Object getJfrEventConfiguration() { } public boolean isReached() { - return classInitializationInfo.isTypeReached(this); + return companion.classInitializationInfo.isTypeReached(this); } private static final class ReflectionDataAccessors { @@ -2147,6 +2079,13 @@ private static SoftReference> getReflec } } + private static final class ClassRedefinedCountAccessors { + @SuppressWarnings("unused") + private static int getClassRedefinedCount(DynamicHub that) { + return 0; + } + } + private static final class ClassLoaderAccessors { @SuppressWarnings("unused") private static ClassLoader getClassLoader(DynamicHub that) { @@ -2187,7 +2126,7 @@ private static void setCachedConstructor(DynamicHub that, Constructor value) } } - private static final class DynamicHubMetadata { + static final class DynamicHubMetadata { @UnknownPrimitiveField(availability = CompileQueueFinished.class) // final int enclosingMethodInfoIndex; @@ -2221,7 +2160,7 @@ private DynamicHubMetadata(int enclosingMethodInfoIndex, int annotationsIndex, i } } - private static final class ReflectionMetadata { + static final class ReflectionMetadata { @UnknownPrimitiveField(availability = CompileQueueFinished.class)// final int fieldsEncodingIndex; @@ -2247,24 +2186,24 @@ private ReflectionMetadata(int fieldsEncodingIndex, int methodsEncodingIndex, in } public FieldDescriptor[] getReachableFields() { - if (reflectionMetadata == null || reflectionMetadata.fieldsEncodingIndex == NO_DATA) { + if (reflectionMetadata() == null || reflectionMetadata().fieldsEncodingIndex == NO_DATA) { return new FieldDescriptor[0]; } - return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseReachableFields(this, reflectionMetadata.fieldsEncodingIndex); + return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseReachableFields(this, reflectionMetadata().fieldsEncodingIndex); } public MethodDescriptor[] getReachableMethods() { - if (reflectionMetadata == null || reflectionMetadata.methodsEncodingIndex == NO_DATA) { + if (reflectionMetadata() == null || reflectionMetadata().methodsEncodingIndex == NO_DATA) { return new MethodDescriptor[0]; } - return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseReachableMethods(this, reflectionMetadata.methodsEncodingIndex); + return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseReachableMethods(this, reflectionMetadata().methodsEncodingIndex); } public ConstructorDescriptor[] getReachableConstructors() { - if (reflectionMetadata == null || reflectionMetadata.constructorsEncodingIndex == NO_DATA) { + if (reflectionMetadata() == null || reflectionMetadata().constructorsEncodingIndex == NO_DATA) { return new ConstructorDescriptor[0]; } - return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseReachableConstructors(this, reflectionMetadata.constructorsEncodingIndex); + return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseReachableConstructors(this, reflectionMetadata().constructorsEncodingIndex); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java index 16f94b255765..a3b995654323 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java @@ -26,24 +26,105 @@ import java.lang.ref.SoftReference; import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; import java.security.ProtectionDomain; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import com.oracle.svm.core.BuildPhaseProvider; +import com.oracle.svm.core.classinitialization.ClassInitializationInfo; +import com.oracle.svm.core.heap.UnknownObjectField; +import com.oracle.svm.core.heap.UnknownPrimitiveField; import com.oracle.svm.core.jdk.ProtectionDomainSupport; +import com.oracle.svm.core.meta.SharedType; import com.oracle.svm.core.util.VMError; +import jdk.internal.vm.annotation.Stable; import sun.reflect.annotation.AnnotationType; import sun.reflect.generics.repository.ClassRepository; /** - * The mutable parts of a {@link DynamicHub} instance. + * Storage for non-critical or mutable data of {@link DynamicHub}. + * + * Some of these fields are immutable and moving them to a separate read-only companion class might + * improve sharing between isolates and processes, but could increase image size. */ public final class DynamicHubCompanion { /** Marker value for {@link #classLoader}. */ private static final Object NO_CLASS_LOADER = new Object(); + /** Field used for module information access at run-time. */ + final Module module; + + /** + * The hub for the superclass, or null if an interface or primitive type. + * + * @see Class#getSuperclass() + */ + final DynamicHub superHub; + + /** Source file name if known; null otherwise. */ + final String sourceFileName; + + /** The {@link Modifier modifiers} of this class. */ + final int modifiers; + + /** The class that serves as the host for the nest. All nestmates have the same host. */ + final Class nestHost; + + /** The simple binary name of this class, as returned by {@code Class.getSimpleBinaryName0}. */ + final String simpleBinaryName; + + /** + * The class that declares this class, as returned by {@code Class.getDeclaringClass0} or an + * exception that happened at image-build time. + */ + final Object declaringClass; + + final String signature; + + /** Similar to {@code DynamicHub.flags}, but set later during the image build. */ + @UnknownPrimitiveField(availability = BuildPhaseProvider.AfterHostedUniverse.class) // + @Stable byte additionalFlags; + + /** + * The hub for an array of this type, or null if the array type has been determined as + * uninstantiated by the static analysis. + */ + @Stable DynamicHub arrayHub; + + /** + * The interfaces that this class implements. Either null (no interfaces), a {@link DynamicHub} + * (one interface), or a {@link DynamicHub}[] array (more than one interface). + */ + @Stable Object interfacesEncoding; + + /** + * Reference to a list of enum values for subclasses of {@link Enum}; null otherwise. + */ + @Stable Object enumConstantsReference; + + /** + * Back link to the SubstrateType used by the substrate meta access. Only used for the subset of + * types for which a SubstrateType exists. + */ + @UnknownObjectField(fullyQualifiedTypes = "com.oracle.svm.graal.meta.SubstrateType", canBeNull = true) // + @Stable SharedType metaType; + + /** + * Metadata for running class initializers at run time. Refers to a singleton marker object for + * classes/interfaces already initialized during image generation, i.e., this field is never + * null at run time. + */ + @Stable ClassInitializationInfo classInitializationInfo; + + @UnknownObjectField(canBeNull = true, availability = BuildPhaseProvider.AfterCompilation.class) // + @Stable DynamicHub.ReflectionMetadata reflectionMetadata; + + @UnknownObjectField(canBeNull = true, availability = BuildPhaseProvider.AfterCompilation.class) // + @Stable DynamicHub.DynamicHubMetadata hubMetadata; + private String packageName; /** * Classloader used for loading this class. Most classes have the correct class loader set @@ -62,15 +143,33 @@ public final class DynamicHubCompanion { private boolean canUnsafeAllocate; @Platforms(Platform.HOSTED_ONLY.class) - DynamicHubCompanion(Class hostedJavaClass, ClassLoader classLoader) { + DynamicHubCompanion(Class hostedJavaClass, Module module, DynamicHub superHub, String sourceFileName, int modifiers, + ClassLoader classLoader, Class nestHost, String simpleBinaryName, Object declaringClass, String signature) { + + this(module, superHub, sourceFileName, modifiers, nestHost, simpleBinaryName, declaringClass, signature); this.classLoader = PredefinedClassesSupport.isPredefined(hostedJavaClass) ? NO_CLASS_LOADER : classLoader; } - DynamicHubCompanion(ClassLoader classLoader) { + DynamicHubCompanion(ClassLoader classLoader, Module module, DynamicHub superHub, String sourceFileName, int modifiers, + Class nestHost, String simpleBinaryName, Object declaringClass, String signature) { + this(module, superHub, sourceFileName, modifiers, nestHost, simpleBinaryName, declaringClass, signature); + assert RuntimeClassLoading.isSupported(); this.classLoader = classLoader; } + private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFileName, int modifiers, + Class nestHost, String simpleBinaryName, Object declaringClass, String signature) { + this.module = module; + this.superHub = superHub; + this.sourceFileName = sourceFileName; + this.modifiers = modifiers; + this.nestHost = nestHost; + this.simpleBinaryName = simpleBinaryName; + this.declaringClass = declaringClass; + this.signature = signature; + } + String getPackageName(DynamicHub hub) { if (packageName == null) { packageName = hub.computePackageName(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index e87c47637c58..8b617d02d40a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -87,6 +87,7 @@ import com.oracle.svm.core.heap.Target_java_lang_ref_Reference; import com.oracle.svm.core.heap.UnknownClass; import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.hub.DynamicHubCompanion; import com.oracle.svm.core.hub.HubType; import com.oracle.svm.core.hub.Hybrid; import com.oracle.svm.core.hub.PredefinedClassesSupport; @@ -887,8 +888,6 @@ private void initializeExcludedFields() { * These fields need to be folded as they are used in snippets, and they must be accessed * without producing reads with side effects. */ - excludedFields.add(ReflectionUtil.lookupField(DynamicHub.class, "arrayHub")); - excludedFields.add(ReflectionUtil.lookupField(DynamicHub.class, "additionalFlags")); excludedFields.add(ReflectionUtil.lookupField(DynamicHub.class, "layoutEncoding")); excludedFields.add(ReflectionUtil.lookupField(DynamicHub.class, "numClassTypes")); excludedFields.add(ReflectionUtil.lookupField(DynamicHub.class, "numInterfaceTypes")); @@ -897,6 +896,9 @@ private void initializeExcludedFields() { excludedFields.add(ReflectionUtil.lookupField(DynamicHub.class, "typeID")); excludedFields.add(ReflectionUtil.lookupField(DynamicHub.class, "monitorOffset")); excludedFields.add(ReflectionUtil.lookupField(DynamicHub.class, "hubType")); + excludedFields.add(ReflectionUtil.lookupField(DynamicHub.class, "companion")); + excludedFields.add(ReflectionUtil.lookupField(DynamicHubCompanion.class, "arrayHub")); + excludedFields.add(ReflectionUtil.lookupField(DynamicHubCompanion.class, "additionalFlags")); /* Needs to be immutable for correct lowering of SubstrateIdentityHashCodeNode. */ excludedFields.add(ReflectionUtil.lookupField(DynamicHub.class, "identityHashOffset")); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java index d58a27506737..f503a0cdc90e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java @@ -44,6 +44,7 @@ import com.oracle.svm.core.BuildPhaseProvider; import com.oracle.svm.core.classinitialization.ClassInitializationInfo; import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.hub.DynamicHubCompanion; import com.oracle.svm.core.meta.MethodPointer; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.BootLoaderSupport; @@ -70,10 +71,10 @@ public class DynamicHubInitializer { private final Map interfacesEncodings; - private final Field dynamicHubClassInitializationInfoField; - private final Field dynamicHubArrayHubField; - private final Field dynamicHubInterfacesEncodingField; - private final Field dynamicHubAnnotationsEnumConstantsReferenceField; + private final Field hubCompanionArrayHubField; + private final Field hubCompanionClassInitializationInfo; + private final Field hubCompanionInterfacesEncoding; + private final Field hubCompanionAnnotationsEnumConstantsReference; public DynamicHubInitializer(BigBang bb) { this.bb = bb; @@ -83,10 +84,10 @@ public DynamicHubInitializer(BigBang bb) { this.interfacesEncodings = new ConcurrentHashMap<>(); - dynamicHubClassInitializationInfoField = ReflectionUtil.lookupField(DynamicHub.class, "classInitializationInfo"); - dynamicHubArrayHubField = ReflectionUtil.lookupField(DynamicHub.class, "arrayHub"); - dynamicHubInterfacesEncodingField = ReflectionUtil.lookupField(DynamicHub.class, "interfacesEncoding"); - dynamicHubAnnotationsEnumConstantsReferenceField = ReflectionUtil.lookupField(DynamicHub.class, "enumConstantsReference"); + hubCompanionArrayHubField = ReflectionUtil.lookupField(DynamicHubCompanion.class, "arrayHub"); + hubCompanionClassInitializationInfo = ReflectionUtil.lookupField(DynamicHubCompanion.class, "classInitializationInfo"); + hubCompanionInterfacesEncoding = ReflectionUtil.lookupField(DynamicHubCompanion.class, "interfacesEncoding"); + hubCompanionAnnotationsEnumConstantsReference = ReflectionUtil.lookupField(DynamicHubCompanion.class, "enumConstantsReference"); } public void initializeMetaData(ImageHeapScanner heapScanner, AnalysisType type) { @@ -131,13 +132,13 @@ public void initializeMetaData(ImageHeapScanner heapScanner, AnalysisType type) AnalysisError.guarantee(hub.getComponentHub().getArrayHub() == null, "Array hub already initialized for %s.", type.getComponentType().toJavaName(true)); hub.getComponentHub().setArrayHub(hub); if (rescan) { - heapScanner.rescanField(hub.getComponentHub(), dynamicHubArrayHubField); + heapScanner.rescanField(hub.getComponentHub().getCompanion(), hubCompanionArrayHubField); } } fillInterfaces(type, hub); if (rescan) { - heapScanner.rescanField(hub, dynamicHubInterfacesEncodingField); + heapScanner.rescanField(hub.getCompanion(), hubCompanionInterfacesEncoding); } /* Support for Java enumerations. */ @@ -149,7 +150,7 @@ public void initializeMetaData(ImageHeapScanner heapScanner, AnalysisType type) hub.initEnumConstants(retrieveEnumConstantArray(type, javaClass)); } if (rescan) { - heapScanner.rescanField(hub, dynamicHubAnnotationsEnumConstantsReferenceField); + heapScanner.rescanField(hub.getCompanion(), hubCompanionAnnotationsEnumConstantsReference); } } } @@ -234,7 +235,7 @@ private void buildClassInitializationInfo(ImageHeapScanner heapScanner, Analysis } hub.setClassInitializationInfo(info); if (rescan) { - heapScanner.rescanField(hub, dynamicHubClassInitializationInfoField); + heapScanner.rescanField(hub.getCompanion(), hubCompanionClassInitializationInfo); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java index 4e7e93915249..97f460454325 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java @@ -89,6 +89,7 @@ import com.oracle.svm.core.classinitialization.ClassInitializationInfo; import com.oracle.svm.core.graal.code.CGlobalDataInfo; import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.hub.DynamicHubCompanion; import com.oracle.svm.core.meta.MethodPointer; import com.oracle.svm.core.reflect.serialize.SerializationSupport; import com.oracle.svm.hosted.FeatureImpl; @@ -103,17 +104,17 @@ import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.ConstantReference; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedAnalysisField; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedAnalysisMethod; -import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedAnalysisType; -import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedConstant; -import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PrimitiveArray; -import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PrimitiveValue; -import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.SharedLayerSnapshot; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedAnalysisMethod.WrappedMethod; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedAnalysisMethod.WrappedMethod.WrappedMember; +import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedAnalysisType; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedAnalysisType.WrappedType; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedAnalysisType.WrappedType.SerializationGenerated; +import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedConstant; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedConstant.Object.Relinking.EnumConstant; import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PersistedConstant.Object.Relinking.StringConstant; +import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PrimitiveArray; +import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.PrimitiveValue; +import com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.SharedLayerSnapshot; import com.oracle.svm.hosted.jni.JNIAccessFeature; import com.oracle.svm.hosted.lambda.LambdaParser; import com.oracle.svm.hosted.meta.HostedUniverse; @@ -145,7 +146,8 @@ import sun.reflect.annotation.AnnotationParser; public class SVMImageLayerLoader extends ImageLayerLoader { - private final Field dynamicHubArrayHubField; + private final Field dynamicHubCompanionField; + private final Field hubCompanionArrayHubField; private final boolean useSharedLayerGraphs; private final SVMImageLayerSnapshotUtil imageLayerSnapshotUtil; private final HostedImageLayerBuildingSupport imageLayerBuildingSupport; @@ -183,7 +185,8 @@ public class SVMImageLayerLoader extends ImageLayerLoader { public SVMImageLayerLoader(SVMImageLayerSnapshotUtil imageLayerSnapshotUtil, HostedImageLayerBuildingSupport imageLayerBuildingSupport, SharedLayerSnapshot.Reader snapshot, FileChannel graphChannel, boolean useSharedLayerGraphs) { - dynamicHubArrayHubField = ReflectionUtil.lookupField(DynamicHub.class, "arrayHub"); + this.dynamicHubCompanionField = ReflectionUtil.lookupField(DynamicHub.class, "companion"); + this.hubCompanionArrayHubField = ReflectionUtil.lookupField(DynamicHubCompanion.class, "arrayHub"); this.imageLayerSnapshotUtil = imageLayerSnapshotUtil; this.imageLayerBuildingSupport = imageLayerBuildingSupport; this.snapshot = snapshot; @@ -1464,7 +1467,8 @@ private void ensureHubInitialized(ImageHeapConstant constant) { * must be created and the initializeMetaDataTask needs to be executed to ensure the * hosted object matches the persisted constant. */ - if (((ImageHeapInstance) constant).getFieldValue(metaAccess.lookupJavaField(dynamicHubArrayHubField)) != JavaConstant.NULL_POINTER && hub.getArrayHub() == null) { + var companion = (ImageHeapInstance) ((ImageHeapInstance) constant).readFieldValue(metaAccess.lookupJavaField(dynamicHubCompanionField)); + if (companion.getFieldValue(metaAccess.lookupJavaField(hubCompanionArrayHubField)) != JavaConstant.NULL_POINTER && hub.getArrayHub() == null) { AnalysisType arrayClass = type.getArrayClass(); ensureHubInitialized(arrayClass); } @@ -1528,14 +1532,14 @@ private static void injectIdentityHashCode(Object object, Integer identityHashCo public void rescanHub(AnalysisType type, Object hubObject) { DynamicHub hub = (DynamicHub) hubObject; universe.getHeapScanner().rescanObject(hub); - universe.getHeapScanner().rescanField(hub, SVMImageLayerSnapshotUtil.classInitializationInfo); + universe.getHeapScanner().rescanField(hub.getCompanion(), SVMImageLayerSnapshotUtil.classInitializationInfo); if (type.getJavaKind() == JavaKind.Object) { if (type.isArray()) { - universe.getHeapScanner().rescanField(hub.getComponentHub(), SVMImageLayerSnapshotUtil.arrayHub); + universe.getHeapScanner().rescanField(hub.getComponentHub().getCompanion(), SVMImageLayerSnapshotUtil.arrayHub); } - universe.getHeapScanner().rescanField(hub, SVMImageLayerSnapshotUtil.interfacesEncoding); + universe.getHeapScanner().rescanField(hub.getCompanion(), SVMImageLayerSnapshotUtil.interfacesEncoding); if (type.isEnum()) { - universe.getHeapScanner().rescanField(hub, SVMImageLayerSnapshotUtil.enumConstantsReference); + universe.getHeapScanner().rescanField(hub.getCompanion(), SVMImageLayerSnapshotUtil.enumConstantsReference); } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java index 5b78e478191f..9c02721fa25c 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java @@ -57,6 +57,7 @@ import com.oracle.graal.pointsto.util.AnalysisError; import com.oracle.svm.core.c.struct.CInterfaceLocationIdentity; import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.hub.DynamicHubCompanion; import com.oracle.svm.core.option.HostedOptionValues; import com.oracle.svm.core.reflect.serialize.SerializationSupport; import com.oracle.svm.core.threadlocal.FastThreadLocal; @@ -101,16 +102,18 @@ public class SVMImageLayerSnapshotUtil { public static final String GENERATED_SERIALIZATION = "jdk.internal.reflect.GeneratedSerializationConstructorAccessor"; - public static final Field companion = ReflectionUtil.lookupField(DynamicHub.class, "companion"); - public static final Field classInitializationInfo = ReflectionUtil.lookupField(DynamicHub.class, "classInitializationInfo"); - private static final Field name = ReflectionUtil.lookupField(DynamicHub.class, "name"); - private static final Field superHub = ReflectionUtil.lookupField(DynamicHub.class, "superHub"); - private static final Field componentType = ReflectionUtil.lookupField(DynamicHub.class, "componentType"); - public static final Field arrayHub = ReflectionUtil.lookupField(DynamicHub.class, "arrayHub"); - public static final Field interfacesEncoding = ReflectionUtil.lookupField(DynamicHub.class, "interfacesEncoding"); - public static final Field enumConstantsReference = ReflectionUtil.lookupField(DynamicHub.class, "enumConstantsReference"); + static final Field companion = ReflectionUtil.lookupField(DynamicHub.class, "companion"); + static final Field name = ReflectionUtil.lookupField(DynamicHub.class, "name"); + static final Field componentType = ReflectionUtil.lookupField(DynamicHub.class, "componentType"); - protected static final Set dynamicHubRelinkedFields = Set.of(companion, classInitializationInfo, name, superHub, componentType, arrayHub); + static final Field classInitializationInfo = ReflectionUtil.lookupField(DynamicHubCompanion.class, "classInitializationInfo"); + static final Field superHub = ReflectionUtil.lookupField(DynamicHubCompanion.class, "superHub"); + static final Field interfacesEncoding = ReflectionUtil.lookupField(DynamicHubCompanion.class, "interfacesEncoding"); + static final Field enumConstantsReference = ReflectionUtil.lookupField(DynamicHubCompanion.class, "enumConstantsReference"); + static final Field arrayHub = ReflectionUtil.lookupField(DynamicHubCompanion.class, "arrayHub"); + + protected static final Set dynamicHubRelinkedFields = Set.of(companion, name, componentType); + protected static final Set dynamicHubCompanionRelinkedFields = Set.of(classInitializationInfo, superHub, arrayHub); /** * This map stores the field indexes that should be relinked using the hosted value of a @@ -187,11 +190,11 @@ public Set getRelinkedFields(AnalysisType type, AnalysisMetaAccess meta Set result = fieldsToRelink.computeIfAbsent(type, key -> { Class clazz = type.getJavaClass(); if (clazz == Class.class) { - type.getInstanceFields(true); - return dynamicHubRelinkedFields.stream().map(metaAccess::lookupJavaField).map(AnalysisField::getPosition).collect(Collectors.toSet()); - } else { - return null; + return getRelinkedFields(type, dynamicHubRelinkedFields, metaAccess); + } else if (clazz == DynamicHubCompanion.class) { + return getRelinkedFields(type, dynamicHubCompanionRelinkedFields, metaAccess); } + return null; }); if (result == null) { return Set.of(); @@ -199,6 +202,11 @@ public Set getRelinkedFields(AnalysisType type, AnalysisMetaAccess meta return result; } + private static Set getRelinkedFields(AnalysisType type, Set typeRelinkedFieldsSet, AnalysisMetaAccess metaAccess) { + type.getInstanceFields(true); + return typeRelinkedFieldsSet.stream().map(metaAccess::lookupJavaField).map(AnalysisField::getPosition).collect(Collectors.toSet()); + } + public SVMGraphEncoder getGraphEncoder(SVMImageLayerWriter imageLayerWriter) { return new SVMGraphEncoder(externalValues, imageLayerWriter); } From 18248a5437c934b28a93ed3975f181e8bf3124c2 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Thu, 19 Dec 2024 15:47:39 +0100 Subject: [PATCH 2/4] Consistently use DynamicHubCompanion directly from DynamicHub. --- .../snippets/SubstrateAllocationSnippets.java | 6 +- .../com/oracle/svm/core/hub/DynamicHub.java | 68 ++++++--- .../svm/core/hub/DynamicHubCompanion.java | 131 +++--------------- .../src/com/oracle/svm/hosted/SVMHost.java | 4 +- 4 files changed, 73 insertions(+), 136 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java index 657a47069e9f..f91f621ebae8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java @@ -36,8 +36,6 @@ import java.util.Arrays; import java.util.Map; -import com.oracle.svm.core.graal.meta.KnownOffsets; -import jdk.graal.compiler.core.common.NumUtil; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.word.LocationIdentity; import org.graalvm.word.UnsignedWord; @@ -48,6 +46,7 @@ import com.oracle.svm.core.allocationprofile.AllocationSite; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.configure.ConfigurationFile; +import com.oracle.svm.core.graal.meta.KnownOffsets; import com.oracle.svm.core.graal.meta.SubstrateForeignCallsProvider; import com.oracle.svm.core.graal.nodes.NewPodInstanceNode; import com.oracle.svm.core.graal.nodes.NewStoredContinuationNode; @@ -75,6 +74,7 @@ import jdk.graal.compiler.api.replacements.Snippet.NonNullParameter; import jdk.graal.compiler.api.replacements.Snippet.VarargsParameter; import jdk.graal.compiler.core.common.GraalOptions; +import jdk.graal.compiler.core.common.NumUtil; import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor; import jdk.graal.compiler.core.common.spi.MetaAccessExtensionProvider; import jdk.graal.compiler.core.common.type.StampFactory; @@ -346,7 +346,7 @@ private static DynamicHub slowPathHubOrUnsafeInstantiationError(DynamicHub hub) throw new InstantiationException("Cannot allocate objects of special hybrid types: " + DynamicHub.toClass(hub).getTypeName()); } else { if (hub.canUnsafeInstantiateAsInstanceSlowPath()) { - hub.getCompanion().setUnsafeAllocate(); + hub.setCanUnsafeAllocate(); return hub; } else { if (MissingRegistrationUtils.throwMissingRegistrationErrors()) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java index 1c0ac3bab6e3..d69ca0e81a6e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java @@ -113,6 +113,7 @@ import com.oracle.svm.core.imagelayer.DynamicImageLayerInfo; import com.oracle.svm.core.jdk.JDK21OrEarlier; import com.oracle.svm.core.jdk.JDKLatest; +import com.oracle.svm.core.jdk.ProtectionDomainSupport; import com.oracle.svm.core.jdk.Resources; import com.oracle.svm.core.meta.SharedType; import com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils; @@ -170,6 +171,9 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ @Substitute // private static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; + /** Marker value for {@link DynamicHubCompanion#classLoader}. */ + static final Object NO_CLASS_LOADER = new Object(); + @Platforms(Platform.HOSTED_ONLY.class) // private final Class hostedJavaClass; @@ -395,8 +399,9 @@ public DynamicHub(Class hostedJavaClass, String name, byte hubType, Reference this.flags = flags; - this.companion = new DynamicHubCompanion(hostedJavaClass, hostedJavaClass.getModule(), superType, sourceFileName, - modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature); + Object loader = PredefinedClassesSupport.isPredefined(hostedJavaClass) ? NO_CLASS_LOADER : classLoader; + this.companion = DynamicHubCompanion.createHosted(hostedJavaClass.getModule(), superType, sourceFileName, + modifiers, loader, nestHost, simpleBinaryName, declaringClass, signature); } /** @@ -430,10 +435,10 @@ public static DynamicHub allocate(String name, DynamicHub superHub, DynamicHub c // GR-59683 Module module = null; - DynamicHubCompanion companion = new DynamicHubCompanion(classLoader, module, superHub, sourceFileName, modifiers, nestHost, simpleBinaryName, declaringClass, signature); + DynamicHubCompanion companion = DynamicHubCompanion.createAtRuntime(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature); /* Always allow unsafe allocation for classes that were loaded at run-time. */ - companion.setUnsafeAllocate(); + companion.canUnsafeAllocate = true; // GR-59687: Correct size and content for vtable int vTableEntries = 0x100; @@ -840,18 +845,26 @@ public boolean isInstantiated() { } public boolean canUnsafeInstantiateAsInstanceFastPath() { - return companion.canUnsafeAllocate(); + return canUnsafeAllocate(); } public boolean canUnsafeInstantiateAsInstanceSlowPath() { if (ClassForNameSupport.canUnsafeInstantiateAsInstance(this)) { - companion.setUnsafeAllocate(); + setCanUnsafeAllocate(); return true; } else { return false; } } + public boolean canUnsafeAllocate() { + return companion.canUnsafeAllocate; + } + + public void setCanUnsafeAllocate() { + companion.canUnsafeAllocate = true; + } + public boolean isProxyClass() { return isFlagSet(flags, IS_PROXY_CLASS_BIT); } @@ -1010,18 +1023,21 @@ public InputStream getResourceAsStream(String resourceName) { @Substitute public ClassLoader getClassLoader() { - return companion.getClassLoader(); + Object loader = companion.classLoader; + VMError.guarantee(loader != NO_CLASS_LOADER); + return (ClassLoader) loader; } @KeepOriginal private native ClassLoader getClassLoader0(); public boolean isLoaded() { - return companion.hasClassLoader(); + return companion.classLoader != NO_CLASS_LOADER; } void setClassLoaderAtRuntime(ClassLoader loader) { - companion.setClassLoader(loader); + VMError.guarantee(companion.classLoader == NO_CLASS_LOADER && loader != NO_CLASS_LOADER); + companion.classLoader = loader; } @KeepOriginal @@ -1613,7 +1629,10 @@ public String getPackageName() { if (SubstrateUtil.HOSTED) { // avoid eager initialization in image heap return computePackageName(); } - return companion.getPackageName(this); + if (companion.packageName == null) { + companion.packageName = computePackageName(); + } + return companion.packageName; } private boolean isHybrid() { @@ -1681,7 +1700,10 @@ public Object[] getSigners() { @Substitute public ProtectionDomain getProtectionDomain() { - return companion.getProtectionDomain(); + if (companion.protectionDomain == null) { + companion.protectionDomain = ProtectionDomainSupport.allPermDomain(); + } + return companion.protectionDomain; } @Substitute @@ -1690,7 +1712,8 @@ private ProtectionDomain protectionDomain() { } void setProtectionDomainAtRuntime(ProtectionDomain protectionDomain) { - companion.setProtectionDomain(protectionDomain); + VMError.guarantee(companion.protectionDomain == null && protectionDomain != null); + companion.protectionDomain = protectionDomain; } @Substitute @@ -1940,7 +1963,10 @@ private Class[] getNestMembers0() { @Substitute private ClassRepository getGenericInfo() { - return companion.getGenericInfo(this); + if (companion.genericInfo == null) { + companion.genericInfo = computeGenericInfo(); + } + return (companion.genericInfo != ClassRepository.NONE) ? companion.genericInfo : null; } ClassRepository computeGenericInfo() { @@ -2061,11 +2087,11 @@ private static Constructor[] filterConstructors(Constructor... constructor } public void setJrfEventConfiguration(Object configuration) { - companion.setJfrEventConfiguration(configuration); + companion.jfrEventConfiguration = configuration; } public Object getJfrEventConfiguration() { - return companion.getJfrEventConfiguration(); + return companion.jfrEventConfiguration; } public boolean isReached() { @@ -2075,7 +2101,7 @@ public boolean isReached() { private static final class ReflectionDataAccessors { @SuppressWarnings("unused") private static SoftReference> getReflectionData(DynamicHub that) { - return that.companion.getReflectionData(); + return that.companion.reflectionData; } } @@ -2089,21 +2115,21 @@ private static int getClassRedefinedCount(DynamicHub that) { private static final class ClassLoaderAccessors { @SuppressWarnings("unused") private static ClassLoader getClassLoader(DynamicHub that) { - return that.companion.getClassLoader(); + return that.getClassLoader(); } } private static final class AnnotationDataAccessors { @SuppressWarnings("unused") private static Target_java_lang_Class_AnnotationData getAnnotationData(DynamicHub that) { - return that.companion.getAnnotationData(); + return that.companion.annotationData; } } private static final class AnnotationTypeAccessors { @SuppressWarnings("unused") private static AnnotationType getAnnotationType(DynamicHub that) { - return that.companion.getAnnotationType(); + return that.companion.annotationType; } } @@ -2117,12 +2143,12 @@ private static Constructor getCachedConstructor(DynamicHub that) { * initialized. We eagerly initialize the class to conform with JCK tests. */ that.ensureInitialized(); - return that.companion.getCachedConstructor(); + return that.companion.cachedConstructor; } @SuppressWarnings("unused") private static void setCachedConstructor(DynamicHub that, Constructor value) { - that.companion.setCachedConstructor(value); + that.companion.cachedConstructor = value; } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java index a3b995654323..62281b4b279a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java @@ -36,9 +36,7 @@ import com.oracle.svm.core.classinitialization.ClassInitializationInfo; import com.oracle.svm.core.heap.UnknownObjectField; import com.oracle.svm.core.heap.UnknownPrimitiveField; -import com.oracle.svm.core.jdk.ProtectionDomainSupport; import com.oracle.svm.core.meta.SharedType; -import com.oracle.svm.core.util.VMError; import jdk.internal.vm.annotation.Stable; import sun.reflect.annotation.AnnotationType; @@ -51,8 +49,6 @@ * improve sharing between isolates and processes, but could increase image size. */ public final class DynamicHubCompanion { - /** Marker value for {@link #classLoader}. */ - private static final Object NO_CLASS_LOADER = new Object(); /** Field used for module information access at run-time. */ final Module module; @@ -125,41 +121,39 @@ public final class DynamicHubCompanion { @UnknownObjectField(canBeNull = true, availability = BuildPhaseProvider.AfterCompilation.class) // @Stable DynamicHub.DynamicHubMetadata hubMetadata; - private String packageName; /** * Classloader used for loading this class. Most classes have the correct class loader set * already at image build time. {@link PredefinedClassesSupport Predefined classes} get their - * classloader only at run time, before "loading" the field value is {@link #NO_CLASS_LOADER}. + * classloader only at run time, before "loading" the field value is + * {@link DynamicHub#NO_CLASS_LOADER}. */ - private Object classLoader; - private ProtectionDomain protectionDomain; - private ClassRepository genericInfo; - private SoftReference> reflectionData; - private AnnotationType annotationType; - private Target_java_lang_Class_AnnotationData annotationData; - private Constructor cachedConstructor; - private Class newInstanceCallerCache; - private Object jfrEventConfiguration; - private boolean canUnsafeAllocate; + Object classLoader; + + String packageName; + ProtectionDomain protectionDomain; + ClassRepository genericInfo; + SoftReference> reflectionData; + AnnotationType annotationType; + Target_java_lang_Class_AnnotationData annotationData; + Constructor cachedConstructor; + Object jfrEventConfiguration; + @Stable boolean canUnsafeAllocate; @Platforms(Platform.HOSTED_ONLY.class) - DynamicHubCompanion(Class hostedJavaClass, Module module, DynamicHub superHub, String sourceFileName, int modifiers, - ClassLoader classLoader, Class nestHost, String simpleBinaryName, Object declaringClass, String signature) { + static DynamicHubCompanion createHosted(Module module, DynamicHub superHub, String sourceFileName, int modifiers, + Object classLoader, Class nestHost, String simpleBinaryName, Object declaringClass, String signature) { - this(module, superHub, sourceFileName, modifiers, nestHost, simpleBinaryName, declaringClass, signature); - this.classLoader = PredefinedClassesSupport.isPredefined(hostedJavaClass) ? NO_CLASS_LOADER : classLoader; + return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature); } - DynamicHubCompanion(ClassLoader classLoader, Module module, DynamicHub superHub, String sourceFileName, int modifiers, - Class nestHost, String simpleBinaryName, Object declaringClass, String signature) { - this(module, superHub, sourceFileName, modifiers, nestHost, simpleBinaryName, declaringClass, signature); - + static DynamicHubCompanion createAtRuntime(Module module, DynamicHub superHub, String sourceFileName, int modifiers, + ClassLoader classLoader, Class nestHost, String simpleBinaryName, Object declaringClass, String signature) { assert RuntimeClassLoading.isSupported(); - this.classLoader = classLoader; + return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature); } private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFileName, int modifiers, - Class nestHost, String simpleBinaryName, Object declaringClass, String signature) { + Object classLoader, Class nestHost, String simpleBinaryName, Object declaringClass, String signature) { this.module = module; this.superHub = superHub; this.sourceFileName = sourceFileName; @@ -168,90 +162,7 @@ private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFil this.simpleBinaryName = simpleBinaryName; this.declaringClass = declaringClass; this.signature = signature; - } - - String getPackageName(DynamicHub hub) { - if (packageName == null) { - packageName = hub.computePackageName(); - } - return packageName; - } - - boolean hasClassLoader() { - return classLoader != NO_CLASS_LOADER; - } - - ClassLoader getClassLoader() { - Object loader = classLoader; - VMError.guarantee(loader != NO_CLASS_LOADER); - return (ClassLoader) loader; - } - - void setClassLoader(ClassLoader loader) { - VMError.guarantee(classLoader == NO_CLASS_LOADER && loader != NO_CLASS_LOADER); - classLoader = loader; - } - - ProtectionDomain getProtectionDomain() { - if (protectionDomain == null) { - protectionDomain = ProtectionDomainSupport.allPermDomain(); - } - return protectionDomain; - } - - void setProtectionDomain(ProtectionDomain domain) { - VMError.guarantee(protectionDomain == null && domain != null); - protectionDomain = domain; - } - - public ClassRepository getGenericInfo(DynamicHub hub) { - if (genericInfo == null) { - genericInfo = hub.computeGenericInfo(); - } - return (genericInfo != ClassRepository.NONE) ? genericInfo : null; - } - - SoftReference> getReflectionData() { - return reflectionData; - } - - AnnotationType getAnnotationType() { - return annotationType; - } - - Target_java_lang_Class_AnnotationData getAnnotationData() { - return annotationData; - } - - Constructor getCachedConstructor() { - return cachedConstructor; - } - - void setCachedConstructor(Constructor constructor) { - cachedConstructor = constructor; - } - - Class getNewInstanceCallerCache() { - return newInstanceCallerCache; - } - - void setNewInstanceCallerCache(Class constructor) { - newInstanceCallerCache = constructor; - } - - public void setJfrEventConfiguration(Object configuration) { - jfrEventConfiguration = configuration; - } - public Object getJfrEventConfiguration() { - return jfrEventConfiguration; - } - - public boolean canUnsafeAllocate() { - return canUnsafeAllocate; - } - - public void setUnsafeAllocate() { - canUnsafeAllocate = true; + this.classLoader = classLoader; } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index 8b617d02d40a..7317be302f81 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -409,7 +409,7 @@ public void onTypeInstantiated(BigBang bb, AnalysisType type) { if (optionAllowUnsafeAllocationOfAllInstantiatedTypes != null) { if (optionAllowUnsafeAllocationOfAllInstantiatedTypes) { type.registerAsUnsafeAllocated("All types are registered as Unsafe allocated via option -H:+AllowUnsafeAllocationOfAllInstantiatedTypes"); - typeToHub.get(type).getCompanion().setUnsafeAllocate(); + typeToHub.get(type).setCanUnsafeAllocate(); } else { /* * No default registration for unsafe allocation, setting the explicit option has @@ -418,7 +418,7 @@ public void onTypeInstantiated(BigBang bb, AnalysisType type) { } } else if (!missingRegistrationSupport.reportMissingRegistrationErrors(type.getJavaClass())) { type.registerAsUnsafeAllocated("Type is not listed as ThrowMissingRegistrationError and therefore registered as Unsafe allocated automatically for compatibility reasons"); - typeToHub.get(type).getCompanion().setUnsafeAllocate(); + typeToHub.get(type).setCanUnsafeAllocate(); } } From 2065c9c7a68116ee5b43fb7325f531a3f8bde7ef Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 20 Dec 2024 19:00:44 +0100 Subject: [PATCH 3/4] Fix layers issues caused by moving arrayHub. --- substratevm/mx.substratevm/mx_substratevm.py | 2 + .../SharedLayerSnapshotCapnProtoSchema.capnp | 11 +-- .../imagelayer/SVMImageLayerLoader.java | 68 ++++++++++++------- .../imagelayer/SVMImageLayerSnapshotUtil.java | 4 +- .../imagelayer/SVMImageLayerWriter.java | 1 + ...redLayerSnapshotCapnProtoSchemaHolder.java | 13 ++++ 6 files changed, 67 insertions(+), 32 deletions(-) diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index ff740f68a193..b8a1c90d376d 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -2520,6 +2520,8 @@ def capnp_compile(args): */ //@formatter:off //Checkstyle: stop +// Generated via: +// $ mx capnp-compile """) for line in lines: if line.startswith("public final class "): diff --git a/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp b/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp index 411cac702b7e..c5adcbaa086d 100644 --- a/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp +++ b/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp @@ -36,16 +36,17 @@ struct PersistedAnalysisType { staticFieldIds @22 :List(FieldId); annotationList @23 :List(Annotation); classInitializationInfo @24 :ClassInitializationInfo; + hasArrayType @25 :Bool; wrappedType :union { - none @25 :Void; # default + none @26 :Void; # default serializationGenerated :group { - rawDeclaringClass @26 :Text; - rawTargetConstructor @27 :Text; + rawDeclaringClass @27 :Text; + rawTargetConstructor @28 :Text; } lambda :group { - capturingClass @28 :Text; + capturingClass @29 :Text; } - proxyType @29 :Void; + proxyType @30 :Void; } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java index 97f460454325..02ded48d5b61 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java @@ -89,7 +89,6 @@ import com.oracle.svm.core.classinitialization.ClassInitializationInfo; import com.oracle.svm.core.graal.code.CGlobalDataInfo; import com.oracle.svm.core.hub.DynamicHub; -import com.oracle.svm.core.hub.DynamicHubCompanion; import com.oracle.svm.core.meta.MethodPointer; import com.oracle.svm.core.reflect.serialize.SerializationSupport; import com.oracle.svm.hosted.FeatureImpl; @@ -147,7 +146,6 @@ public class SVMImageLayerLoader extends ImageLayerLoader { private final Field dynamicHubCompanionField; - private final Field hubCompanionArrayHubField; private final boolean useSharedLayerGraphs; private final SVMImageLayerSnapshotUtil imageLayerSnapshotUtil; private final HostedImageLayerBuildingSupport imageLayerBuildingSupport; @@ -186,7 +184,6 @@ public class SVMImageLayerLoader extends ImageLayerLoader { public SVMImageLayerLoader(SVMImageLayerSnapshotUtil imageLayerSnapshotUtil, HostedImageLayerBuildingSupport imageLayerBuildingSupport, SharedLayerSnapshot.Reader snapshot, FileChannel graphChannel, boolean useSharedLayerGraphs) { this.dynamicHubCompanionField = ReflectionUtil.lookupField(DynamicHub.class, "companion"); - this.hubCompanionArrayHubField = ReflectionUtil.lookupField(DynamicHubCompanion.class, "arrayHub"); this.imageLayerSnapshotUtil = imageLayerSnapshotUtil; this.imageLayerBuildingSupport = imageLayerBuildingSupport; this.snapshot = snapshot; @@ -583,19 +580,28 @@ private int getBaseLayerTypeId(AnalysisType type) { if (type.getWrapped() instanceof BaseLayerType baseLayerType) { return baseLayerType.getBaseLayerId(); } - String typeDescriptor = imageLayerSnapshotUtil.getTypeDescriptor(type); - Integer typeId = typeDescriptorToBaseLayerId.get(typeDescriptor); - if (typeId == null) { + PersistedAnalysisType.Reader typeData = findBaseLayerType(type); + if (typeData == null) { /* The type was not reachable in the base image */ return -1; } - PersistedAnalysisType.Reader typeData = findType(typeId); int id = typeData.getId(); int hubIdentityHashCode = typeData.getHubIdentityHashCode(); typeToHubIdentityHashCode.put(id, hubIdentityHashCode); return id; } + protected PersistedAnalysisType.Reader findBaseLayerType(AnalysisType type) { + assert !(type.getWrapped() instanceof BaseLayerType); + String typeDescriptor = imageLayerSnapshotUtil.getTypeDescriptor(type); + Integer typeId = typeDescriptorToBaseLayerId.get(typeDescriptor); + if (typeId == null) { + /* The type was not reachable in the base image */ + return null; + } + return findType(typeId); + } + @Override public void initializeBaseLayerType(AnalysisType type) { int id = getBaseLayerTypeId(type); @@ -1252,14 +1258,17 @@ private Object[] getReferencedValues(ImageHeapConstant parentConstant, StructLis JavaConstant hostedConstant = relink ? getReachableHostedValue(parentConstant, finalPosition) : null; ImageHeapConstant baseLayerConstant = getOrCreateConstant(constantId, hostedConstant); - values[finalPosition] = baseLayerConstant; - ensureHubInitialized(baseLayerConstant); if (hostedConstant != null) { addBaseLayerValueToImageHeap(baseLayerConstant, parentConstant, finalPosition); } + /* + * The value needs to be published after the constant is added to the image + * heap, as a non-base layer constant could then be created. + */ + values[finalPosition] = baseLayerConstant; return baseLayerConstant; }); } @@ -1463,12 +1472,12 @@ private void ensureHubInitialized(ImageHeapConstant constant) { AnalysisType type = ((SVMHost) universe.hostVM()).lookupType(hub); ensureHubInitialized(type); /* - * If the persisted constant contains a non-null arrayHub, the corresponding DynamicHub - * must be created and the initializeMetaDataTask needs to be executed to ensure the - * hosted object matches the persisted constant. + * If the persisted hub has a non-null arrayHub, the corresponding DynamicHub must be + * created and the initializeMetaDataTask needs to be executed to ensure the hosted + * object matches the persisted constant. */ - var companion = (ImageHeapInstance) ((ImageHeapInstance) constant).readFieldValue(metaAccess.lookupJavaField(dynamicHubCompanionField)); - if (companion.getFieldValue(metaAccess.lookupJavaField(hubCompanionArrayHubField)) != JavaConstant.NULL_POINTER && hub.getArrayHub() == null) { + PersistedAnalysisType.Reader typeData = findBaseLayerType(type); + if (typeData != null && typeData.getHasArrayType()) { AnalysisType arrayClass = type.getArrayClass(); ensureHubInitialized(arrayClass); } @@ -1529,21 +1538,30 @@ private static void injectIdentityHashCode(Object object, Integer identityHashCo } } - public void rescanHub(AnalysisType type, Object hubObject) { - DynamicHub hub = (DynamicHub) hubObject; - universe.getHeapScanner().rescanObject(hub); - universe.getHeapScanner().rescanField(hub.getCompanion(), SVMImageLayerSnapshotUtil.classInitializationInfo); - if (type.getJavaKind() == JavaKind.Object) { - if (type.isArray()) { - universe.getHeapScanner().rescanField(hub.getComponentHub().getCompanion(), SVMImageLayerSnapshotUtil.arrayHub); - } - universe.getHeapScanner().rescanField(hub.getCompanion(), SVMImageLayerSnapshotUtil.interfacesEncoding); - if (type.isEnum()) { - universe.getHeapScanner().rescanField(hub.getCompanion(), SVMImageLayerSnapshotUtil.enumConstantsReference); + public void rescanHub(AnalysisType type, DynamicHub hub) { + if (hasValueForObject(hub)) { + universe.getHeapScanner().rescanObject(hub); + scanCompanionField(hub); + universe.getHeapScanner().rescanField(hub.getCompanion(), SVMImageLayerSnapshotUtil.classInitializationInfo); + if (type.getJavaKind() == JavaKind.Object) { + if (type.isArray()) { + DynamicHub componentHub = hub.getComponentHub(); + scanCompanionField(componentHub); + universe.getHeapScanner().rescanField(componentHub.getCompanion(), SVMImageLayerSnapshotUtil.arrayHub); + } + universe.getHeapScanner().rescanField(hub.getCompanion(), SVMImageLayerSnapshotUtil.interfacesEncoding); + if (type.isEnum()) { + universe.getHeapScanner().rescanField(hub.getCompanion(), SVMImageLayerSnapshotUtil.enumConstantsReference); + } } } } + private void scanCompanionField(DynamicHub hub) { + var instance = (ImageHeapInstance) getValueForObject(hub); + instance.readFieldValue(metaAccess.lookupJavaField(dynamicHubCompanionField)); + } + public ClassInitializationInfo getClassInitializationInfo(AnalysisType type) { PersistedAnalysisType.Reader typeMap = findType(type.getId()); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java index 9c02721fa25c..85bc2fa7cf05 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java @@ -34,10 +34,10 @@ import java.lang.reflect.Field; import java.net.URI; import java.net.URISyntaxException; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import org.graalvm.nativeimage.ImageSingletons; @@ -119,7 +119,7 @@ public class SVMImageLayerSnapshotUtil { * This map stores the field indexes that should be relinked using the hosted value of a * constant from the key type. */ - protected final Map> fieldsToRelink = new HashMap<>(); + protected final Map> fieldsToRelink = new ConcurrentHashMap<>(); private final ImageClassLoader imageClassLoader; protected final List externalValueFields; /** This needs to be initialized after analysis, as some fields are not available before. */ diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java index ecb7e5063914..e81a67abf1a2 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java @@ -391,6 +391,7 @@ private void persistType(AnalysisType type, Supplier Date: Tue, 14 Jan 2025 19:39:36 +0100 Subject: [PATCH 4/4] Claim ownership of com.oracle.svm.core.hub. --- .../com.oracle.svm.core/src/com/oracle/svm/core/hub/OWNERS.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/OWNERS.toml b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/OWNERS.toml index 1f7d0b0a8706..b8a198d08ff3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/OWNERS.toml +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/OWNERS.toml @@ -2,6 +2,7 @@ files = "*" all = [ "christian.haeubl@oracle.com", + "peter.hofer@oracle.com", ] any = [ ]