Skip to content

Commit c521f01

Browse files
author
Christian Wimmer
committed
Review fixes
1 parent 7fa6385 commit c521f01

File tree

4 files changed

+53
-55
lines changed

4 files changed

+53
-55
lines changed

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import static org.graalvm.compiler.replacements.StandardGraphBuilderPlugins.registerInvocationPlugins;
3232

3333
import java.io.IOException;
34+
import java.lang.annotation.Annotation;
3435
import java.lang.ref.Reference;
3536
import java.lang.reflect.Method;
3637
import java.lang.reflect.Modifier;
@@ -292,6 +293,7 @@
292293
import com.oracle.svm.hosted.substitute.DeletedFieldsPlugin;
293294
import com.oracle.svm.hosted.substitute.UnsafeAutomaticSubstitutionProcessor;
294295
import com.oracle.svm.util.AnnotationExtracter;
296+
import com.oracle.svm.util.ClassUtil;
295297
import com.oracle.svm.util.ImageBuildStatistics;
296298
import com.oracle.svm.util.ReflectionUtil;
297299
import com.oracle.svm.util.ReflectionUtil.ReflectionUtilError;
@@ -1602,7 +1604,7 @@ private void processNativeLibraryImports(NativeLibraries nativeLibs, MetaAccessP
16021604

16031605
for (Method method : loader.findAnnotatedMethods(CConstant.class)) {
16041606
if (LibCBase.isMethodProvidedInCurrentLibc(method)) {
1605-
classInitializationSupport.initializeAtBuildTime(method.getDeclaringClass(), "classes with " + CConstant.class.getSimpleName() + " annotations are always initialized");
1607+
initializeAtBuildTime(method.getDeclaringClass(), classInitializationSupport, CConstant.class);
16061608
nativeLibs.loadJavaMethod(metaAccess.lookupJavaMethod(method));
16071609
}
16081610
}
@@ -1613,38 +1615,38 @@ private void processNativeLibraryImports(NativeLibraries nativeLibs, MetaAccessP
16131615
}
16141616
for (Class<?> clazz : loader.findAnnotatedClasses(CStruct.class, false)) {
16151617
if (LibCBase.isTypeProvidedInCurrentLibc(clazz)) {
1616-
classInitializationSupport.initializeAtBuildTime(clazz, "classes annotated with " + CStruct.class.getSimpleName() + " are always initialized");
1618+
initializeAtBuildTime(clazz, classInitializationSupport, CStruct.class);
16171619
nativeLibs.loadJavaType(metaAccess.lookupJavaType(clazz));
16181620
}
16191621
}
16201622
for (Class<?> clazz : loader.findAnnotatedClasses(RawStructure.class, false)) {
16211623
if (LibCBase.isTypeProvidedInCurrentLibc(clazz)) {
1622-
classInitializationSupport.initializeAtBuildTime(clazz, "classes annotated with " + RawStructure.class.getSimpleName() + " are always initialized");
1624+
initializeAtBuildTime(clazz, classInitializationSupport, RawStructure.class);
16231625
nativeLibs.loadJavaType(metaAccess.lookupJavaType(clazz));
16241626
}
16251627
}
16261628
for (Class<?> clazz : loader.findAnnotatedClasses(CPointerTo.class, false)) {
16271629
if (LibCBase.isTypeProvidedInCurrentLibc(clazz)) {
1628-
classInitializationSupport.initializeAtBuildTime(clazz, "classes annotated with " + CPointerTo.class.getSimpleName() + " are always initialized");
1630+
initializeAtBuildTime(clazz, classInitializationSupport, CPointerTo.class);
16291631
nativeLibs.loadJavaType(metaAccess.lookupJavaType(clazz));
16301632
}
16311633
}
16321634
for (Class<?> clazz : loader.findAnnotatedClasses(RawPointerTo.class, false)) {
16331635
if (LibCBase.isTypeProvidedInCurrentLibc(clazz)) {
1634-
classInitializationSupport.initializeAtBuildTime(clazz, "classes annotated with " + RawPointerTo.class.getSimpleName() + " are always initialized");
1636+
initializeAtBuildTime(clazz, classInitializationSupport, RawPointerTo.class);
16351637
nativeLibs.loadJavaType(metaAccess.lookupJavaType(clazz));
16361638
}
16371639
}
16381640
for (Class<?> clazz : loader.findAnnotatedClasses(CEnum.class, false)) {
16391641
if (LibCBase.isTypeProvidedInCurrentLibc(clazz)) {
16401642
ResolvedJavaType type = metaAccess.lookupJavaType(clazz);
1641-
classInitializationSupport.initializeAtBuildTime(clazz, "classes annotated with " + CEnum.class.getSimpleName() + " are always initialized");
1643+
initializeAtBuildTime(clazz, classInitializationSupport, CEnum.class);
16421644
nativeLibs.loadJavaType(type);
16431645
}
16441646
}
16451647
for (Class<?> clazz : loader.findAnnotatedClasses(CContext.class, false)) {
16461648
if (LibCBase.isTypeProvidedInCurrentLibc(clazz)) {
1647-
classInitializationSupport.initializeAtBuildTime(clazz, "classes annotated with " + CContext.class.getSimpleName() + " are always initialized");
1649+
initializeAtBuildTime(clazz, classInitializationSupport, CContext.class);
16481650
}
16491651
}
16501652
nativeLibs.processCLibraryAnnotations(loader);
@@ -1653,6 +1655,12 @@ private void processNativeLibraryImports(NativeLibraries nativeLibs, MetaAccessP
16531655
nativeLibs.reportErrors();
16541656
}
16551657

1658+
private static void initializeAtBuildTime(Class<?> clazz, ClassInitializationSupport classInitializationSupport, Class<? extends Annotation> annotationForMessage) {
1659+
String message = "classes annotated with " + ClassUtil.getUnqualifiedName(annotationForMessage) + " are always initialized at image build time";
1660+
classInitializationSupport.initializeAtBuildTime(clazz, message);
1661+
classInitializationSupport.forceInitializeHosted(clazz, message, false);
1662+
}
1663+
16561664
public AbstractImage getBuiltImage() {
16571665
return image;
16581666
}

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

Lines changed: 31 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import com.oracle.svm.core.util.VMError;
3535
import com.oracle.svm.hosted.ImageClassLoader;
3636

37-
import jdk.internal.misc.Unsafe;
3837
import jdk.vm.ci.meta.MetaAccessProvider;
3938

4039
class AllowAllHostedUsagesClassInitializationSupport extends ClassInitializationSupport {
@@ -43,23 +42,42 @@ class AllowAllHostedUsagesClassInitializationSupport extends ClassInitialization
4342
super(metaAccess, loader);
4443
}
4544

45+
@Override
46+
public void initializeAtBuildTime(Class<?> aClass, String reason) {
47+
UserError.guarantee(!configurationSealed, "The class initialization configuration can be changed only before the phase analysis.");
48+
Class<?> cur = aClass;
49+
do {
50+
classInitializationConfiguration.insert(cur.getTypeName(), InitKind.BUILD_TIME, cur == aClass ? reason : "super type of " + aClass.getTypeName(), true);
51+
initializeInterfacesAtBuildTime(cur.getInterfaces(), "interface of " + aClass.getTypeName());
52+
cur = cur.getSuperclass();
53+
} while (cur != null);
54+
}
55+
56+
private void initializeInterfacesAtBuildTime(Class<?>[] interfaces, String reason) {
57+
for (Class<?> iface : interfaces) {
58+
if (metaAccess.lookupJavaType(iface).declaresDefaultMethods()) {
59+
classInitializationConfiguration.insert(iface.getTypeName(), InitKind.BUILD_TIME, reason, true);
60+
}
61+
initializeInterfacesAtBuildTime(iface.getInterfaces(), reason);
62+
}
63+
}
64+
4665
@Override
4766
public void initializeAtRunTime(Class<?> clazz, String reason) {
4867
UserError.guarantee(!configurationSealed, "The class initialization configuration can be changed only before the phase analysis.");
4968
classInitializationConfiguration.insert(clazz.getTypeName(), InitKind.RUN_TIME, reason, true);
50-
setSubclassesAsRunTime(clazz);
5169
}
5270

5371
@Override
5472
public void rerunInitialization(Class<?> clazz, String reason) {
55-
UserError.guarantee(!configurationSealed, "The class initialization configuration can be changed only before the phase analysis.");
56-
classInitializationConfiguration.insert(clazz.getTypeName(), InitKind.RERUN, reason, true);
73+
/* There is no more difference between RUN_TIME and RERUN. */
74+
initializeAtRunTime(clazz, reason);
75+
}
5776

58-
try {
59-
Unsafe.getUnsafe().ensureClassInitialized(clazz);
60-
} catch (Throwable ex) {
61-
throw UserError.abort(ex, "Class initialization failed for %s. The class is requested for re-running (reason: %s)", clazz.getTypeName(), reason);
62-
}
77+
@Override
78+
public void rerunInitialization(String name, String reason) {
79+
/* There is no more difference between RUN_TIME and RERUN. */
80+
initializeAtRunTime(name, reason);
6381
}
6482

6583
@Override
@@ -75,21 +93,6 @@ String reasonForClass(Class<?> clazz) {
7593
}
7694
}
7795

78-
private void setSubclassesAsRunTime(Class<?> clazz) {
79-
if (clazz.isInterface() && !metaAccess.lookupJavaType(clazz).declaresDefaultMethods()) {
80-
/*
81-
* An interface that does not declare a default method is independent from a class
82-
* initialization point of view, i.e., it is not initialized when a class implementing
83-
* that interface is initialized.
84-
*/
85-
return;
86-
}
87-
loader.findSubclasses(clazz, false).stream()
88-
.filter(c -> !c.equals(clazz))
89-
.filter(c -> !(c.isInterface() && !metaAccess.lookupJavaType(c).declaresDefaultMethods()))
90-
.forEach(c -> classInitializationConfiguration.insert(c.getTypeName(), InitKind.RUN_TIME, "subtype of " + clazz.getTypeName(), true));
91-
}
92-
9396
@Override
9497
public void forceInitializeHosted(Class<?> clazz, String reason, boolean allowInitializationErrors) {
9598
if (clazz == null) {
@@ -149,11 +152,6 @@ InitKind computeInitKindAndMaybeInitializeClass(Class<?> clazz, boolean memoize)
149152
return InitKind.BUILD_TIME;
150153
}
151154

152-
if (clazz.getTypeName().contains("$$StringConcat")) {
153-
forceInitializeHosted(clazz, "string concatenation classes are initialized at build time", false);
154-
return InitKind.BUILD_TIME;
155-
}
156-
157155
InitKind specifiedInitKind = specifiedInitKindFor(clazz);
158156
InitKind clazzResult = specifiedInitKind != null ? specifiedInitKind : InitKind.RUN_TIME;
159157

@@ -175,18 +173,10 @@ InitKind computeInitKindAndMaybeInitializeClass(Class<?> clazz, boolean memoize)
175173
result = result.max(ensureClassInitialized(clazz, false));
176174
}
177175

178-
/*
179-
* Unfortunately, the computation of canInitializeWithoutSideEffects is not completely
180-
* deterministic: Consider a class A whose class initializer depends on class B. Assume
181-
* class B has no other dependencies and can therefore be initialized at build time.
182-
* When class A is analyzed after class B has been initialized, it can also be
183-
* initialized at build time. But when class A is analyzed before class B has been
184-
* initialized, it cannot. Since two threads can analyze class A at the same time (there
185-
* is no per-class locking) and another thread can initialize B at the same time, we can
186-
* have a conflicting initialization status. In that case, BUILD_TIME must win over
187-
* RUN_TIME because one thread has already initialized class A.
188-
*/
189-
result = classInitKinds.merge(clazz, result, InitKind::min);
176+
InitKind previous = classInitKinds.putIfAbsent(clazz, result);
177+
if (previous != null && previous != result) {
178+
throw VMError.shouldNotReachHere("Conflicting class initialization kind: " + previous + " != " + result + " for " + clazz);
179+
}
190180
}
191181
return result;
192182
}

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

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -318,13 +318,6 @@ static String getTraceString(StackTraceElement[] trace) {
318318
return b.toString();
319319
}
320320

321-
@Override
322-
public void initializeAtBuildTime(Class<?> aClass, String reason) {
323-
UserError.guarantee(!configurationSealed, "The class initialization configuration can be changed only before the phase analysis.");
324-
classInitializationConfiguration.insert(aClass.getTypeName(), InitKind.BUILD_TIME, reason, true);
325-
forceInitializeHosted(aClass, reason, false);
326-
}
327-
328321
@Override
329322
public void reportClassInitialized(Class<?> clazz, StackTraceElement[] stackTrace) {
330323
assert TraceClassInitialization.hasBeenSet();

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,13 @@ public void rerunInitialization(Class<?> clazz, String reason) {
188188
}
189189
}
190190

191+
@Override
192+
public void initializeAtBuildTime(Class<?> aClass, String reason) {
193+
UserError.guarantee(!configurationSealed, "The class initialization configuration can be changed only before the phase analysis.");
194+
classInitializationConfiguration.insert(aClass.getTypeName(), InitKind.BUILD_TIME, reason, true);
195+
forceInitializeHosted(aClass, reason, false);
196+
}
197+
191198
private void setSubclassesAsRunTime(Class<?> clazz) {
192199
if (clazz.isInterface() && !metaAccess.lookupJavaType(clazz).declaresDefaultMethods()) {
193200
/*

0 commit comments

Comments
 (0)