Skip to content

Commit 6577748

Browse files
[GR-68875] Fix class initialization problems.
PullRequest: graal/22021
2 parents d47c6e1 + 217ae38 commit 6577748

File tree

9 files changed

+516
-397
lines changed

9 files changed

+516
-397
lines changed

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

Lines changed: 456 additions & 292 deletions
Large diffs are not rendered by default.

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,15 @@ public final class EnsureClassInitializedSnippets extends SubstrateTemplates imp
6767
@Snippet
6868
private static void ensureClassIsInitializedSnippet(@Snippet.NonNullParameter DynamicHub hub) {
6969
ClassInitializationInfo info = hub.getClassInitializationInfo();
70-
/*
71-
* The ClassInitializationInfo field is always initialized by the image generator. We can
72-
* save the explicit null check.
73-
*/
70+
/* The ClassInitializationInfo field is always non-null. */
7471
ClassInitializationInfo infoNonNull = (ClassInitializationInfo) PiNode.piCastNonNull(info, SnippetAnchorNode.anchor());
75-
76-
if (BranchProbabilityNode.probability(BranchProbabilityNode.EXTREMELY_SLOW_PATH_PROBABILITY, infoNonNull.requiresSlowPath())) {
77-
callSlowPath(SLOW_PATH, infoNonNull, DynamicHub.toClass(hub));
72+
if (BranchProbabilityNode.probability(BranchProbabilityNode.EXTREMELY_SLOW_PATH_PROBABILITY, infoNonNull.isSlowPathRequired())) {
73+
callSlowPath(SLOW_PATH, DynamicHub.toClass(hub));
7874
}
7975
}
8076

8177
@NodeIntrinsic(value = ForeignCallWithExceptionNode.class)
82-
private static native void callSlowPath(@ConstantNodeParameter ForeignCallDescriptor descriptor, ClassInitializationInfo info, Class<?> clazz);
78+
private static native void callSlowPath(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> hub);
8379

8480
@SuppressWarnings("unused")
8581
public static void registerLowerings(OptionValues options, Providers providers, Map<Class<? extends Node>, NodeLoweringProvider<?>> lowerings) {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[[rule]]
2+
files = "*"
3+
all = [
4+
5+
6+
]
7+
any = [
8+
]

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -507,8 +507,7 @@ public static DynamicHub allocate(String name, DynamicHub superHub, Object inter
507507

508508
/* Always allow unsafe allocation for classes that were loaded at run-time. */
509509
companion.canUnsafeAllocate = true;
510-
511-
companion.classInitializationInfo = new ClassInitializationInfo(false);
510+
companion.classInitializationInfo = ClassInitializationInfo.forRuntimeLoadedClass(false);
512511

513512
assert !isFlagSet(flags, IS_PRIMITIVE_FLAG_BIT);
514513
boolean isInterface = isFlagSet(flags, IS_INTERFACE_FLAG_BIT);

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

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,13 @@ struct PersistedAnalysisType {
6666
}
6767

6868
struct ClassInitializationInfo {
69-
isNoInitializerNoTracking @0 :Bool;
70-
isInitializedNoTracking @1 :Bool;
71-
isFailedNoTracking @2 :Bool;
72-
isInitialized @3 :Bool;
73-
isInErrorState @4 :Bool;
74-
isLinked @5 :Bool;
75-
hasInitializer @6 :Bool;
76-
isBuildTimeInitialized @7 :Bool;
77-
isTracked @8 :Bool;
78-
initializerMethodId @9 :MethodId;
69+
isInitialized @0 :Bool;
70+
isInErrorState @1 :Bool;
71+
isLinked @2 :Bool;
72+
hasInitializer @3 :Bool;
73+
isBuildTimeInitialized @4 :Bool;
74+
isTracked @5 :Bool;
75+
initializerMethodId @6 :MethodId;
7976
}
8077

8178
struct PersistedAnalysisMethod {

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
*/
2525
package com.oracle.svm.hosted.analysis;
2626

27+
import static com.oracle.svm.core.classinitialization.ClassInitializationInfo.InitState.FullyInitialized;
28+
import static com.oracle.svm.core.classinitialization.ClassInitializationInfo.InitState.InitializationError;
29+
2730
import java.lang.reflect.Field;
2831
import java.util.Arrays;
2932
import java.util.Map;
@@ -245,17 +248,18 @@ private Enum<?>[] retrieveEnumConstantArray(AnalysisType type, Class<?> javaClas
245248

246249
private void buildClassInitializationInfo(ImageHeapScanner heapScanner, AnalysisType type, DynamicHub hub, boolean rescan) {
247250
AnalysisError.guarantee(hub.getClassInitializationInfo() == null, "Class initialization info already computed for %s.", type.toJavaName(true));
248-
boolean initializedOrSimulated = SimulateClassInitializerSupport.singleton().trySimulateClassInitializer(bb, type);
249251
ClassInitializationInfo info;
250252
if (type.getWrapped() instanceof BaseLayerType) {
251253
info = layerLoader.getClassInitializationInfo(type);
252254
} else {
255+
boolean hasInitializer = type.getClassInitializer() != null;
253256
boolean typeReachedTracked = ClassInitializationSupport.singleton().requiresInitializationNodeForTypeReached(type);
257+
boolean initializedOrSimulated = SimulateClassInitializerSupport.singleton().trySimulateClassInitializer(bb, type);
258+
254259
if (initializedOrSimulated) {
255-
info = type.getClassInitializer() == null ? ClassInitializationInfo.forNoInitializerInfo(typeReachedTracked)
256-
: ClassInitializationInfo.forInitializedInfo(typeReachedTracked);
260+
info = ClassInitializationInfo.forBuildTimeInitializedClass(FullyInitialized, hasInitializer, typeReachedTracked);
257261
} else {
258-
info = buildRuntimeInitializationInfo(type, typeReachedTracked);
262+
info = buildRuntimeInitializationInfo(type, hasInitializer, typeReachedTracked);
259263
}
260264
VMError.guarantee(!type.isInBaseLayer() || layerLoader.isInitializationInfoStable(type, info));
261265
}
@@ -265,26 +269,25 @@ private void buildClassInitializationInfo(ImageHeapScanner heapScanner, Analysis
265269
}
266270
}
267271

268-
private ClassInitializationInfo buildRuntimeInitializationInfo(AnalysisType type, boolean typeReachedTracked) {
272+
private ClassInitializationInfo buildRuntimeInitializationInfo(AnalysisType type, boolean hasInitializer, boolean typeReachedTracked) {
269273
assert !type.isInitialized();
270274
try {
271275
/*
272276
* Check if there are any linking errors. This method throws an error even if linking
273277
* already failed in a previous attempt.
274278
*/
275279
type.link();
276-
277280
} catch (VerifyError e) {
278281
/* Synthesize a VerifyError to be thrown at run time. */
279282
AnalysisMethod throwVerifyError = metaAccess.lookupJavaMethod(ExceptionSynthesizer.throwExceptionMethod(VerifyError.class));
280283
bb.addRootMethod(throwVerifyError, true, "Class initialization error, registered in " + DynamicHubInitializer.class);
281-
return new ClassInitializationInfo(new MethodPointer(throwVerifyError), typeReachedTracked);
284+
return ClassInitializationInfo.forRuntimeTimeInitializedClass(new MethodPointer(throwVerifyError), typeReachedTracked);
282285
} catch (Throwable t) {
283286
/*
284287
* All other linking errors will be reported as NoClassDefFoundError when initialization
285288
* is attempted at run time.
286289
*/
287-
return ClassInitializationInfo.forFailedInfo(typeReachedTracked);
290+
return ClassInitializationInfo.forBuildTimeInitializedClass(InitializationError, hasInitializer, typeReachedTracked);
288291
}
289292

290293
/*
@@ -299,7 +302,7 @@ private ClassInitializationInfo buildRuntimeInitializationInfo(AnalysisType type
299302
bb.addRootMethod(classInitializer, true, "Class initialization, registered in " + DynamicHubInitializer.class);
300303
classInitializerFunction = new MethodPointer(classInitializer);
301304
}
302-
return new ClassInitializationInfo(classInitializerFunction, typeReachedTracked);
305+
return ClassInitializationInfo.forRuntimeTimeInitializedClass(classInitializerFunction, typeReachedTracked);
303306
}
304307

305308
class InterfacesEncodingKey {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
package com.oracle.svm.hosted.imagelayer;
2626

2727
import static com.oracle.graal.pointsto.util.AnalysisError.guarantee;
28+
import static com.oracle.svm.core.classinitialization.ClassInitializationInfo.InitState.FullyInitialized;
29+
import static com.oracle.svm.core.classinitialization.ClassInitializationInfo.InitState.InitializationError;
2830
import static com.oracle.svm.hosted.imagelayer.SVMImageLayerSnapshotUtil.CLASS_INIT_NAME;
2931
import static com.oracle.svm.hosted.imagelayer.SVMImageLayerSnapshotUtil.CONSTRUCTOR_NAME;
3032
import static com.oracle.svm.hosted.imagelayer.SVMImageLayerSnapshotUtil.PERSISTED;
@@ -1865,28 +1867,14 @@ public ClassInitializationInfo getClassInitializationInfo(AnalysisType aType) {
18651867
return null;
18661868
}
18671869
var initInfo = typeData.getClassInitializationInfo();
1868-
if (initInfo.getIsNoInitializerNoTracking()) {
1869-
return ClassInitializationInfo.forNoInitializerInfo(false);
1870-
} else if (initInfo.getIsInitializedNoTracking()) {
1871-
return ClassInitializationInfo.forInitializedInfo(false);
1872-
} else if (initInfo.getIsFailedNoTracking()) {
1873-
return ClassInitializationInfo.forFailedInfo(false);
1870+
if (initInfo.getIsInitialized() || initInfo.getIsInErrorState()) {
1871+
ClassInitializationInfo.InitState initState = initInfo.getIsInitialized() ? FullyInitialized : InitializationError;
1872+
return ClassInitializationInfo.forBuildTimeInitializedClass(initState, initInfo.getHasInitializer(), initInfo.getIsTracked());
18741873
} else {
1875-
boolean isTracked = initInfo.getIsTracked();
1876-
1877-
ClassInitializationInfo.InitState initState;
1878-
if (initInfo.getIsInitialized()) {
1879-
initState = ClassInitializationInfo.InitState.FullyInitialized;
1880-
} else if (initInfo.getIsInErrorState()) {
1881-
initState = ClassInitializationInfo.InitState.InitializationError;
1882-
} else {
1883-
assert initInfo.getIsLinked() : "Invalid state";
1884-
int classInitializerId = initInfo.getInitializerMethodId();
1885-
MethodPointer classInitializer = (classInitializerId == 0) ? null : new MethodPointer(getAnalysisMethodForBaseLayerId(classInitializerId));
1886-
return new ClassInitializationInfo(classInitializer, isTracked);
1887-
}
1888-
1889-
return new ClassInitializationInfo(initState, initInfo.getHasInitializer(), initInfo.getIsBuildTimeInitialized(), isTracked);
1874+
assert initInfo.getIsLinked() : "Invalid state";
1875+
int classInitializerId = initInfo.getInitializerMethodId();
1876+
MethodPointer classInitializer = (classInitializerId == 0) ? null : new MethodPointer(getAnalysisMethodForBaseLayerId(classInitializerId));
1877+
return ClassInitializationInfo.forRuntimeTimeInitializedClass(classInitializer, initInfo.getIsTracked());
18901878
}
18911879
}
18921880

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -454,16 +454,13 @@ private void persistType(AnalysisType type, Supplier<PersistedAnalysisType.Build
454454
} else {
455455
builder.setHasClassInitInfo(true);
456456
Builder b = builder.initClassInitializationInfo();
457-
b.setIsNoInitializerNoTracking(info == ClassInitializationInfo.forNoInitializerInfo(false));
458-
b.setIsInitializedNoTracking(info == ClassInitializationInfo.forInitializedInfo(false));
459-
b.setIsFailedNoTracking(info == ClassInitializationInfo.forFailedInfo(false));
460457
b.setIsInitialized(info.isInitialized());
461458
b.setIsInErrorState(info.isInErrorState());
462459
b.setIsLinked(info.isLinked());
463460
b.setHasInitializer(info.hasInitializer());
464461
b.setIsBuildTimeInitialized(info.isBuildTimeInitialized());
465462
b.setIsTracked(info.isTracked());
466-
FunctionPointerHolder classInitializer = info.getClassInitializer();
463+
FunctionPointerHolder classInitializer = info.getRuntimeClassInitializer();
467464
if (classInitializer != null) {
468465
MethodPointer methodPointer = (MethodPointer) classInitializer.functionPointer;
469466
AnalysisMethod classInitializerMethod = (AnalysisMethod) methodPointer.getMethod();

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SharedLayerSnapshotCapnProtoSchemaHolder.java

Lines changed: 18 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -861,67 +861,46 @@ public static final class Builder extends com.oracle.svm.shaded.org.capnproto.St
861861
public final Reader asReader() {
862862
return new Reader(segment, data, pointers, dataSize, pointerCount, 0x7fffffff);
863863
}
864-
public final boolean getIsNoInitializerNoTracking() {
865-
return _getBooleanField(0);
866-
}
867-
public final void setIsNoInitializerNoTracking(boolean value) {
868-
_setBooleanField(0, value);
869-
}
870-
871-
public final boolean getIsInitializedNoTracking() {
872-
return _getBooleanField(1);
873-
}
874-
public final void setIsInitializedNoTracking(boolean value) {
875-
_setBooleanField(1, value);
876-
}
877-
878-
public final boolean getIsFailedNoTracking() {
879-
return _getBooleanField(2);
880-
}
881-
public final void setIsFailedNoTracking(boolean value) {
882-
_setBooleanField(2, value);
883-
}
884-
885864
public final boolean getIsInitialized() {
886-
return _getBooleanField(3);
865+
return _getBooleanField(0);
887866
}
888867
public final void setIsInitialized(boolean value) {
889-
_setBooleanField(3, value);
868+
_setBooleanField(0, value);
890869
}
891870

892871
public final boolean getIsInErrorState() {
893-
return _getBooleanField(4);
872+
return _getBooleanField(1);
894873
}
895874
public final void setIsInErrorState(boolean value) {
896-
_setBooleanField(4, value);
875+
_setBooleanField(1, value);
897876
}
898877

899878
public final boolean getIsLinked() {
900-
return _getBooleanField(5);
879+
return _getBooleanField(2);
901880
}
902881
public final void setIsLinked(boolean value) {
903-
_setBooleanField(5, value);
882+
_setBooleanField(2, value);
904883
}
905884

906885
public final boolean getHasInitializer() {
907-
return _getBooleanField(6);
886+
return _getBooleanField(3);
908887
}
909888
public final void setHasInitializer(boolean value) {
910-
_setBooleanField(6, value);
889+
_setBooleanField(3, value);
911890
}
912891

913892
public final boolean getIsBuildTimeInitialized() {
914-
return _getBooleanField(7);
893+
return _getBooleanField(4);
915894
}
916895
public final void setIsBuildTimeInitialized(boolean value) {
917-
_setBooleanField(7, value);
896+
_setBooleanField(4, value);
918897
}
919898

920899
public final boolean getIsTracked() {
921-
return _getBooleanField(8);
900+
return _getBooleanField(5);
922901
}
923902
public final void setIsTracked(boolean value) {
924-
_setBooleanField(8, value);
903+
_setBooleanField(5, value);
925904
}
926905

927906
public final int getInitializerMethodId() {
@@ -938,40 +917,28 @@ public static final class Reader extends com.oracle.svm.shaded.org.capnproto.Str
938917
super(segment, data, pointers, dataSize, pointerCount, nestingLimit);
939918
}
940919

941-
public final boolean getIsNoInitializerNoTracking() {
942-
return _getBooleanField(0);
943-
}
944-
945-
public final boolean getIsInitializedNoTracking() {
946-
return _getBooleanField(1);
947-
}
948-
949-
public final boolean getIsFailedNoTracking() {
950-
return _getBooleanField(2);
951-
}
952-
953920
public final boolean getIsInitialized() {
954-
return _getBooleanField(3);
921+
return _getBooleanField(0);
955922
}
956923

957924
public final boolean getIsInErrorState() {
958-
return _getBooleanField(4);
925+
return _getBooleanField(1);
959926
}
960927

961928
public final boolean getIsLinked() {
962-
return _getBooleanField(5);
929+
return _getBooleanField(2);
963930
}
964931

965932
public final boolean getHasInitializer() {
966-
return _getBooleanField(6);
933+
return _getBooleanField(3);
967934
}
968935

969936
public final boolean getIsBuildTimeInitialized() {
970-
return _getBooleanField(7);
937+
return _getBooleanField(4);
971938
}
972939

973940
public final boolean getIsTracked() {
974-
return _getBooleanField(8);
941+
return _getBooleanField(5);
975942
}
976943

977944
public final int getInitializerMethodId() {

0 commit comments

Comments
 (0)