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.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/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 b987d124633b..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
@@ -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;
@@ -114,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;
@@ -143,18 +143,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)
@@ -165,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;
@@ -323,26 +332,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 +343,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 +352,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 +366,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 +384,24 @@ 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);
+ Object loader = PredefinedClassesSupport.isPredefined(hostedJavaClass) ? NO_CLASS_LOADER : classLoader;
+ this.companion = DynamicHubCompanion.createHosted(hostedJavaClass.getModule(), superType, sourceFileName,
+ modifiers, loader, nestHost, simpleBinaryName, declaringClass, signature);
}
/**
@@ -503,15 +427,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 = DynamicHubCompanion.createAtRuntime(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature);
- DynamicHubCompanion companion = new DynamicHubCompanion(classLoader);
/* 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;
- 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 +456,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 +506,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 +558,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 +577,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 +609,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 +694,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 +717,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 +730,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 +742,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 +814,7 @@ public int getIdentityHashOffset() {
}
public DynamicHub getSuperHub() {
- return superHub;
+ return companion.superHub;
}
public DynamicHub getComponentHub() {
@@ -888,7 +822,7 @@ public DynamicHub getComponentHub() {
}
public DynamicHub getArrayHub() {
- return arrayHub;
+ return companion.arrayHub;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
@@ -907,22 +841,30 @@ public int getLayerId() {
}
public boolean isInstantiated() {
- return isFlagSet(additionalFlags, IS_INSTANTIATED_BIT);
+ return isFlagSet(companion.additionalFlags, ADDITIONAL_FLAGS_INSTANTIATED_BIT);
}
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);
}
@@ -1002,11 +944,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 +958,7 @@ private DynamicHub getComponentType() {
@Substitute
private DynamicHub getSuperclass() {
- return superHub;
+ return companion.superHub;
}
@Substitute
@@ -1057,6 +999,7 @@ private boolean isEnum() {
@Substitute
public Object[] getEnumConstantsShared() {
+ Object enumConstantsReference = companion.enumConstantsReference;
if (enumConstantsReference instanceof LazyFinalReference) {
return (Object[]) ((LazyFinalReference>) enumConstantsReference).get();
}
@@ -1069,7 +1012,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
@@ -1080,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
@@ -1174,6 +1120,7 @@ public boolean isRegisteredForSerialization() {
@Substitute
private Class> getDeclaringClass0() {
+ Object declaringClass = companion.declaringClass;
if (declaringClass == null) {
return null;
} else if (declaringClass instanceof Class) {
@@ -1477,12 +1424,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
@@ -1682,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() {
@@ -1742,15 +1692,18 @@ 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
public ProtectionDomain getProtectionDomain() {
- return companion.getProtectionDomain();
+ if (companion.protectionDomain == null) {
+ companion.protectionDomain = ProtectionDomainSupport.allPermDomain();
+ }
+ return companion.protectionDomain;
}
@Substitute
@@ -1759,7 +1712,8 @@ private ProtectionDomain protectionDomain() {
}
void setProtectionDomainAtRuntime(ProtectionDomain protectionDomain) {
- companion.setProtectionDomain(protectionDomain);
+ VMError.guarantee(companion.protectionDomain == null && protectionDomain != null);
+ companion.protectionDomain = protectionDomain;
}
@Substitute
@@ -1769,7 +1723,7 @@ public boolean desiredAssertionStatus() {
@Substitute //
public Module getModule() {
- return module;
+ return companion.module;
}
@Substitute //
@@ -1795,7 +1749,7 @@ private static String describeMethod(String prefix, Class>[] argTypes, String
@Substitute //
private String getSimpleBinaryName0() {
- return simpleBinaryName;
+ return companion.simpleBinaryName;
}
/**
@@ -1834,12 +1788,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 +1811,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 +1844,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 +1856,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 +1876,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 +1902,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 +1945,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());
}
@@ -2008,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() {
@@ -2042,10 +2000,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());
}
@@ -2129,42 +2087,49 @@ 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() {
- return classInitializationInfo.isTypeReached(this);
+ return companion.classInitializationInfo.isTypeReached(this);
}
private static final class ReflectionDataAccessors {
@SuppressWarnings("unused")
private static SoftReference> getReflectionData(DynamicHub that) {
- return that.companion.getReflectionData();
+ return that.companion.reflectionData;
+ }
+ }
+
+ 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) {
- 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;
}
}
@@ -2178,16 +2143,16 @@ 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;
}
}
- private static final class DynamicHubMetadata {
+ static final class DynamicHubMetadata {
@UnknownPrimitiveField(availability = CompileQueueFinished.class) //
final int enclosingMethodInfoIndex;
@@ -2221,7 +2186,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 +2212,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..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
@@ -26,133 +26,143 @@
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.jdk.ProtectionDomainSupport;
-import com.oracle.svm.core.util.VMError;
+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.meta.SharedType;
+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();
- private String packageName;
+ /** Field used for module information access at run-time. */
+ final Module module;
+
/**
- * 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}.
+ * The hub for the superclass, or null if an interface or primitive type.
+ *
+ * @see Class#getSuperclass()
*/
- 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;
+ final DynamicHub superHub;
- @Platforms(Platform.HOSTED_ONLY.class)
- DynamicHubCompanion(Class> hostedJavaClass, ClassLoader classLoader) {
- this.classLoader = PredefinedClassesSupport.isPredefined(hostedJavaClass) ? NO_CLASS_LOADER : classLoader;
- }
+ /** Source file name if known; null otherwise. */
+ final String sourceFileName;
- DynamicHubCompanion(ClassLoader classLoader) {
- assert RuntimeClassLoading.isSupported();
- this.classLoader = classLoader;
- }
+ /** The {@link Modifier modifiers} of this class. */
+ final int modifiers;
- String getPackageName(DynamicHub hub) {
- if (packageName == null) {
- packageName = hub.computePackageName();
- }
- return packageName;
- }
+ /** The class that serves as the host for the nest. All nestmates have the same host. */
+ final Class> nestHost;
- boolean hasClassLoader() {
- return classLoader != NO_CLASS_LOADER;
- }
+ /** The simple binary name of this class, as returned by {@code Class.getSimpleBinaryName0}. */
+ final String simpleBinaryName;
- ClassLoader getClassLoader() {
- Object loader = classLoader;
- VMError.guarantee(loader != NO_CLASS_LOADER);
- return (ClassLoader) loader;
- }
+ /**
+ * The class that declares this class, as returned by {@code Class.getDeclaringClass0} or an
+ * exception that happened at image-build time.
+ */
+ final Object declaringClass;
- void setClassLoader(ClassLoader loader) {
- VMError.guarantee(classLoader == NO_CLASS_LOADER && loader != NO_CLASS_LOADER);
- classLoader = loader;
- }
+ final String signature;
- ProtectionDomain getProtectionDomain() {
- if (protectionDomain == null) {
- protectionDomain = ProtectionDomainSupport.allPermDomain();
- }
- return protectionDomain;
- }
+ /** Similar to {@code DynamicHub.flags}, but set later during the image build. */
+ @UnknownPrimitiveField(availability = BuildPhaseProvider.AfterHostedUniverse.class) //
+ @Stable byte additionalFlags;
- void setProtectionDomain(ProtectionDomain domain) {
- VMError.guarantee(protectionDomain == null && domain != null);
- protectionDomain = domain;
- }
+ /**
+ * 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;
- public ClassRepository getGenericInfo(DynamicHub hub) {
- if (genericInfo == null) {
- genericInfo = hub.computeGenericInfo();
- }
- return (genericInfo != ClassRepository.NONE) ? genericInfo : null;
- }
+ /**
+ * 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;
- SoftReference> getReflectionData() {
- return reflectionData;
- }
+ /**
+ * Reference to a list of enum values for subclasses of {@link Enum}; null otherwise.
+ */
+ @Stable Object enumConstantsReference;
- AnnotationType getAnnotationType() {
- return annotationType;
- }
+ /**
+ * 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;
- Target_java_lang_Class_AnnotationData getAnnotationData() {
- return annotationData;
- }
+ /**
+ * 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;
- Constructor> getCachedConstructor() {
- return cachedConstructor;
- }
+ @UnknownObjectField(canBeNull = true, availability = BuildPhaseProvider.AfterCompilation.class) //
+ @Stable DynamicHub.ReflectionMetadata reflectionMetadata;
- void setCachedConstructor(Constructor> constructor) {
- cachedConstructor = constructor;
- }
+ @UnknownObjectField(canBeNull = true, availability = BuildPhaseProvider.AfterCompilation.class) //
+ @Stable DynamicHub.DynamicHubMetadata hubMetadata;
- Class> getNewInstanceCallerCache() {
- return newInstanceCallerCache;
- }
+ /**
+ * 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 DynamicHub#NO_CLASS_LOADER}.
+ */
+ 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;
- void setNewInstanceCallerCache(Class> constructor) {
- newInstanceCallerCache = constructor;
- }
+ @Platforms(Platform.HOSTED_ONLY.class)
+ static DynamicHubCompanion createHosted(Module module, DynamicHub superHub, String sourceFileName, int modifiers,
+ Object classLoader, Class> nestHost, String simpleBinaryName, Object declaringClass, String signature) {
- public void setJfrEventConfiguration(Object configuration) {
- jfrEventConfiguration = configuration;
+ return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature);
}
- public Object getJfrEventConfiguration() {
- return jfrEventConfiguration;
+ static DynamicHubCompanion createAtRuntime(Module module, DynamicHub superHub, String sourceFileName, int modifiers,
+ ClassLoader classLoader, Class> nestHost, String simpleBinaryName, Object declaringClass, String signature) {
+ assert RuntimeClassLoading.isSupported();
+ return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature);
}
- public boolean canUnsafeAllocate() {
- return canUnsafeAllocate;
- }
+ private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFileName, int modifiers,
+ Object classLoader, 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;
- public void setUnsafeAllocate() {
- canUnsafeAllocate = true;
+ this.classLoader = classLoader;
}
}
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 = [
]
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/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java
index e87c47637c58..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
@@ -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;
@@ -408,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
@@ -417,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();
}
}
@@ -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..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
@@ -103,17 +103,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 +145,7 @@
import sun.reflect.annotation.AnnotationParser;
public class SVMImageLayerLoader extends ImageLayerLoader {
- private final Field dynamicHubArrayHubField;
+ private final Field dynamicHubCompanionField;
private final boolean useSharedLayerGraphs;
private final SVMImageLayerSnapshotUtil imageLayerSnapshotUtil;
private final HostedImageLayerBuildingSupport imageLayerBuildingSupport;
@@ -183,7 +183,7 @@ 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.imageLayerSnapshotUtil = imageLayerSnapshotUtil;
this.imageLayerBuildingSupport = imageLayerBuildingSupport;
this.snapshot = snapshot;
@@ -580,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);
@@ -1249,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;
});
}
@@ -1460,11 +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.
*/
- if (((ImageHeapInstance) constant).getFieldValue(metaAccess.lookupJavaField(dynamicHubArrayHubField)) != JavaConstant.NULL_POINTER && hub.getArrayHub() == null) {
+ PersistedAnalysisType.Reader typeData = findBaseLayerType(type);
+ if (typeData != null && typeData.getHasArrayType()) {
AnalysisType arrayClass = type.getArrayClass();
ensureHubInitialized(arrayClass);
}
@@ -1525,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, SVMImageLayerSnapshotUtil.classInitializationInfo);
- if (type.getJavaKind() == JavaKind.Object) {
- if (type.isArray()) {
- universe.getHeapScanner().rescanField(hub.getComponentHub(), SVMImageLayerSnapshotUtil.arrayHub);
- }
- universe.getHeapScanner().rescanField(hub, SVMImageLayerSnapshotUtil.interfacesEncoding);
- if (type.isEnum()) {
- universe.getHeapScanner().rescanField(hub, 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 5b78e478191f..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;
@@ -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,22 +102,24 @@ 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
* 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. */
@@ -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);
}
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