Skip to content

Commit 2c69390

Browse files
committed
Refactor layered class initialization: load base layer simulation result.
1 parent afaec4b commit 2c69390

13 files changed

+322
-97
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/classinitialization/ClassInitializationInfo.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
import java.util.concurrent.locks.Condition;
2828
import java.util.concurrent.locks.ReentrantLock;
2929

30-
import com.oracle.svm.core.hub.RuntimeClassLoading;
31-
import jdk.graal.compiler.word.Word;
3230
import org.graalvm.nativeimage.CurrentIsolate;
3331
import org.graalvm.nativeimage.IsolateThread;
3432
import org.graalvm.nativeimage.Platform;
@@ -39,13 +37,15 @@
3937
import com.oracle.svm.core.c.InvokeJavaFunctionPointer;
4038
import com.oracle.svm.core.hub.DynamicHub;
4139
import com.oracle.svm.core.hub.PredefinedClassesSupport;
40+
import com.oracle.svm.core.hub.RuntimeClassLoading;
4241
import com.oracle.svm.core.jdk.InternalVMMethod;
4342
import com.oracle.svm.core.snippets.SubstrateForeignCallTarget;
4443
import com.oracle.svm.core.thread.ContinuationSupport;
4544
import com.oracle.svm.core.thread.JavaThreads;
4645
import com.oracle.svm.core.thread.Target_jdk_internal_vm_Continuation;
4746
import com.oracle.svm.core.util.VMError;
4847

48+
import jdk.graal.compiler.word.Word;
4949
import jdk.internal.misc.Unsafe;
5050
import jdk.internal.reflect.Reflection;
5151

@@ -246,6 +246,14 @@ public ClassInitializationInfo(boolean typeReachedTracked) {
246246
this.initLock = new ReentrantLock();
247247
}
248248

249+
public InitState getInitState() {
250+
return initState;
251+
}
252+
253+
public boolean isSlowPathRequired() {
254+
return slowPathRequired;
255+
}
256+
249257
public boolean hasInitializer() {
250258
return hasInitializer;
251259
}

substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,38 @@ struct PersistedAnalysisType {
2929
isInitialized @9 :Bool;
3030
# True if the type was configured as initialized at BUILD_TIME but initialization failed so it was registered as RUN_TIME.
3131
isFailedInitialization @10 :Bool;
32-
isLinked @11 :Bool;
33-
sourceFileName @12 :Text;
34-
enclosingTypeId @13 :TypeId;
35-
componentTypeId @14 :TypeId;
36-
superClassTypeId @15 :TypeId;
37-
isInstantiated @16 :Bool;
38-
isUnsafeAllocated @17 :Bool;
39-
isReachable @18 :Bool;
40-
interfaces @19 :List(TypeId);
41-
instanceFieldIds @20 :List(FieldId);
42-
instanceFieldIdsWithSuper @21 :List(FieldId);
43-
staticFieldIds @22 :List(FieldId);
44-
annotationList @23 :List(Annotation);
45-
classInitializationInfo @24 :ClassInitializationInfo;
46-
hasArrayType @25 :Bool;
47-
subTypes @26 :List(TypeId);
48-
isAnySubtypeInstantiated @27 :Bool;
32+
# Type's initializer simulation succeeded. We'll also persist simulated field values.
33+
isSuccessfulSimulation @11 :Bool;
34+
# Type's initializer simulation failed.
35+
isFailedSimulation @12 :Bool;
36+
isLinked @13 :Bool;
37+
sourceFileName @14 :Text;
38+
enclosingTypeId @15 :TypeId;
39+
componentTypeId @16 :TypeId;
40+
superClassTypeId @17 :TypeId;
41+
isInstantiated @18 :Bool;
42+
isUnsafeAllocated @19 :Bool;
43+
isReachable @20 :Bool;
44+
interfaces @21 :List(TypeId);
45+
instanceFieldIds @22 :List(FieldId);
46+
instanceFieldIdsWithSuper @23 :List(FieldId);
47+
staticFieldIds @24 :List(FieldId);
48+
annotationList @25 :List(Annotation);
49+
classInitializationInfo @26 :ClassInitializationInfo;
50+
hasArrayType @27 :Bool;
51+
hasClassInitInfo @28 :Bool;
52+
subTypes @29 :List(TypeId);
53+
isAnySubtypeInstantiated @30 :Bool;
4954
wrappedType :union {
50-
none @28 :Void; # default
55+
none @31 :Void; # default
5156
serializationGenerated :group {
52-
rawDeclaringClass @29 :Text;
53-
rawTargetConstructor @30 :Text;
57+
rawDeclaringClass @32 :Text;
58+
rawTargetConstructor @33 :Text;
5459
}
5560
lambda :group {
56-
capturingClass @31 :Text;
61+
capturingClass @34 :Text;
5762
}
58-
proxyType @32 :Void;
63+
proxyType @35 :Void;
5964
}
6065
}
6166

@@ -151,6 +156,7 @@ struct PersistedAnalysisField {
151156
name @16 :Text;
152157
priorInstalledLayerNum @17 :Int32;
153158
assignmentStatus @18 :Int32;
159+
simulatedFieldValue @19 :ConstantReference;
154160
}
155161

156162
struct CEntryPointLiteralReference {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,8 +1017,9 @@ protected void setupNativeImage(OptionValues options, Map<Method, CEntryPointDat
10171017
aUniverse = createAnalysisUniverse(options, target, loader, originalMetaAccess, annotationSubstitutions, cEnumProcessor,
10181018
classInitializationSupport, Collections.singletonList(harnessSubstitutions), missingRegistrationSupport);
10191019

1020+
SVMImageLayerWriter imageLayerWriter = null;
10201021
if (ImageLayerBuildingSupport.buildingSharedLayer()) {
1021-
SVMImageLayerWriter imageLayerWriter = HostedImageLayerBuildingSupport.singleton().getWriter();
1022+
imageLayerWriter = HostedImageLayerBuildingSupport.singleton().getWriter();
10221023
aUniverse.setImageLayerWriter(imageLayerWriter);
10231024
imageLayerWriter.setAnalysisUniverse(aUniverse);
10241025
}
@@ -1045,7 +1046,11 @@ protected void setupNativeImage(OptionValues options, Map<Method, CEntryPointDat
10451046
HostedProviders aProviders = createHostedProviders(target, aUniverse, originalProviders, platformConfig, aMetaAccess, classInitializationSupport);
10461047
aUniverse.hostVM().initializeProviders(aProviders);
10471048

1048-
ImageSingletons.add(SimulateClassInitializerSupport.class, (hostVM).createSimulateClassInitializerSupport(aMetaAccess));
1049+
SimulateClassInitializerSupport simulateClassInitializerSupport = hostVM.createSimulateClassInitializerSupport(aMetaAccess);
1050+
ImageSingletons.add(SimulateClassInitializerSupport.class, simulateClassInitializerSupport);
1051+
if (imageLayerWriter != null) {
1052+
imageLayerWriter.setSimulateClassInitializerSupport(simulateClassInitializerSupport);
1053+
}
10491054

10501055
bb = createBigBang(debug, options, aUniverse, aMetaAccess, aProviders, annotationSubstitutions);
10511056
aUniverse.setBigBang(bb);
@@ -1064,8 +1069,8 @@ protected void setupNativeImage(OptionValues options, Map<Method, CEntryPointDat
10641069
ImageHeapScanner heapScanner = new SVMImageHeapScanner(bb, imageHeap, loader, aMetaAccess, aProviders.getSnippetReflection(),
10651070
aProviders.getConstantReflection(), aScanningObserver, hostedValuesProvider);
10661071
aUniverse.setHeapScanner(heapScanner);
1067-
if (ImageLayerBuildingSupport.buildingSharedLayer()) {
1068-
HostedImageLayerBuildingSupport.singleton().getWriter().setImageHeap(imageHeap);
1072+
if (imageLayerWriter != null) {
1073+
imageLayerWriter.setImageHeap(imageHeap);
10691074
}
10701075
((HostedSnippetReflectionProvider) aProviders.getSnippetReflection()).setHeapScanner(heapScanner);
10711076
if (imageLayerLoader != null) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
import java.util.Map;
3030
import java.util.concurrent.ConcurrentHashMap;
3131

32-
import com.oracle.svm.core.encoder.IdentitySymbolEncoder;
33-
import com.oracle.svm.core.encoder.SymbolEncoder;
3432
import org.graalvm.nativeimage.c.function.CFunctionPointer;
3533

3634
import com.oracle.graal.pointsto.BigBang;
@@ -45,6 +43,8 @@
4543
import com.oracle.graal.pointsto.util.AnalysisError;
4644
import com.oracle.svm.core.BuildPhaseProvider;
4745
import com.oracle.svm.core.classinitialization.ClassInitializationInfo;
46+
import com.oracle.svm.core.encoder.IdentitySymbolEncoder;
47+
import com.oracle.svm.core.encoder.SymbolEncoder;
4848
import com.oracle.svm.core.hub.DynamicHub;
4949
import com.oracle.svm.core.hub.DynamicHubCompanion;
5050
import com.oracle.svm.core.hub.RuntimeClassLoading;
@@ -57,6 +57,7 @@
5757
import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport;
5858
import com.oracle.svm.hosted.classinitialization.SimulateClassInitializerSupport;
5959
import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport;
60+
import com.oracle.svm.hosted.imagelayer.SVMImageLayerLoader;
6061
import com.oracle.svm.hosted.jdk.HostedClassLoaderPackageManagement;
6162
import com.oracle.svm.util.ReflectionUtil;
6263

@@ -81,6 +82,7 @@ public class DynamicHubInitializer {
8182
private final Field hubCompanionInterfacesEncoding;
8283
private final Field hubCompanionAnnotationsEnumConstantsReference;
8384
private final Field hubCompanionInterpreterType;
85+
private final SVMImageLayerLoader layerLoader;
8486

8587
public DynamicHubInitializer(BigBang bb) {
8688
this.bb = bb;
@@ -96,6 +98,7 @@ public DynamicHubInitializer(BigBang bb) {
9698
hubCompanionInterfacesEncoding = ReflectionUtil.lookupField(DynamicHubCompanion.class, "interfacesEncoding");
9799
hubCompanionAnnotationsEnumConstantsReference = ReflectionUtil.lookupField(DynamicHubCompanion.class, "enumConstantsReference");
98100
hubCompanionInterpreterType = ReflectionUtil.lookupField(DynamicHubCompanion.class, "interpreterType");
101+
layerLoader = HostedImageLayerBuildingSupport.singleton().getLoader();
99102
}
100103

101104
public void initializeMetaData(ImageHeapScanner heapScanner, AnalysisType type) {
@@ -242,18 +245,19 @@ private Enum<?>[] retrieveEnumConstantArray(AnalysisType type, Class<?> javaClas
242245

243246
private void buildClassInitializationInfo(ImageHeapScanner heapScanner, AnalysisType type, DynamicHub hub, boolean rescan) {
244247
AnalysisError.guarantee(hub.getClassInitializationInfo() == null, "Class initialization info already computed for %s.", type.toJavaName(true));
245-
boolean initializedAtBuildTime = SimulateClassInitializerSupport.singleton().trySimulateClassInitializer(bb, type);
248+
boolean initializedOrSimulated = SimulateClassInitializerSupport.singleton().trySimulateClassInitializer(bb, type);
246249
ClassInitializationInfo info;
247250
if (type.getWrapped() instanceof BaseLayerType) {
248-
info = HostedImageLayerBuildingSupport.singleton().getLoader().getClassInitializationInfo(type);
251+
info = layerLoader.getClassInitializationInfo(type);
249252
} else {
250253
boolean typeReachedTracked = ClassInitializationSupport.singleton().requiresInitializationNodeForTypeReached(type);
251-
if (initializedAtBuildTime) {
254+
if (initializedOrSimulated) {
252255
info = type.getClassInitializer() == null ? ClassInitializationInfo.forNoInitializerInfo(typeReachedTracked)
253256
: ClassInitializationInfo.forInitializedInfo(typeReachedTracked);
254257
} else {
255258
info = buildRuntimeInitializationInfo(type, typeReachedTracked);
256259
}
260+
VMError.guarantee(!type.isInBaseLayer() || layerLoader.isInitializationInfoStable(type, info));
257261
}
258262
hub.setClassInitializationInfo(info);
259263
if (rescan) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ private void reportKind(AfterAnalysisAccessImpl access, PrintWriter writer, Init
290290
if (kind != BUILD_TIME) {
291291
Optional<AnalysisType> type = access.getMetaAccess().optionalLookupJavaType(clazz);
292292
if (type.isPresent()) {
293-
simulated = SimulateClassInitializerSupport.singleton().isClassInitializerSimulated(type.get());
293+
simulated = SimulateClassInitializerSupport.singleton().isSimulatedOrInitializedAtBuildTime(type.get());
294294
}
295295
}
296296
if (simulated) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerClusterMember.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ public final class SimulateClassInitializerClusterMember {
4646
final AnalysisType type;
4747

4848
final EconomicSet<SimulateClassInitializerClusterMember> dependencies = EconomicSet.create();
49+
/** Keeps track of why the type could not be simulated as initialized. */
4950
final List<Object> notInitializedReasons = new ArrayList<>();
51+
/** The values resulting from a successful simulation. */
5052
final EconomicMap<AnalysisField, JavaConstant> staticFieldValues = EconomicMap.create();
5153

5254
/** The mutable status field of the cluster member. */

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerConstantFieldProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@ final class SimulateClassInitializerConstantFieldProvider extends AnalysisConsta
4848

4949
@Override
5050
protected boolean isClassInitialized(ResolvedJavaField field) {
51-
return support.isClassInitializerSimulated((AnalysisType) field.getDeclaringClass());
51+
return support.isSimulatedOrInitializedAtBuildTime((AnalysisType) field.getDeclaringClass());
5252
}
5353
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerResult.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,16 @@
4040
*/
4141
final class SimulateClassInitializerResult {
4242

43+
/** We didn't try simulation either because the feature is disabled or type's linking failed. */
4344
static final SimulateClassInitializerResult NOT_SIMULATED_INITIALIZED = new SimulateClassInitializerResult(false, null);
45+
/** We tried simulating the type's initializer but failed. */
46+
static final SimulateClassInitializerResult FAILED_SIMULATED_INITIALIZED = new SimulateClassInitializerResult(false, null);
47+
/** Type was already initialized in the host VM. We didn't try to simulate it. */
4448
static final SimulateClassInitializerResult INITIALIZED_HOSTED = SimulateClassInitializerResult.forInitialized(EconomicMap.emptyMap());
4549

50+
/** True if the class initializer was successfully simulated as initialized. */
4651
final boolean simulatedInitialized;
52+
/** The simulated field values published in case of a successful simulation. */
4753
final UnmodifiableEconomicMap<AnalysisField, JavaConstant> staticFieldValues;
4854

4955
static SimulateClassInitializerResult forInitialized(EconomicMap<AnalysisField, JavaConstant> staticFieldValues) {

0 commit comments

Comments
 (0)