Skip to content

Commit e69b8a7

Browse files
author
Christian Wimmer
committed
Simulate class initializer
1 parent eb44770 commit e69b8a7

File tree

41 files changed

+3173
-802
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+3173
-802
lines changed

compiler/src/jdk.internal.vm.compiler.test/src/org/graalvm/compiler/core/test/VerifyDebugUsage.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ protected void verify(StructuredGraph graph, CoreProviders context) {
122122
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run",
123123
"org.graalvm.compiler.hotspot.SymbolicSnippetEncoder.verifySnippetEncodeDecode",
124124
"com.oracle.graal.pointsto.phases.InlineBeforeAnalysis.decodeGraph",
125+
"com.oracle.svm.hosted.classinitialization.SimulateClassInitializerSupport.decodeGraph",
126+
"com.oracle.svm.hosted.classinitialization.SimulateClassInitializerAbortException.doAbort",
125127
"org.graalvm.compiler.truffle.compiler.phases.inlining.CallTree.dumpBasic",
126128
"org.graalvm.compiler.truffle.compiler.phases.inlining.GraphManager.peRoot"));
127129

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This changelog summarizes major changes to GraalVM Native Image.
66
* (GR-35746) Lower the default aligned chunk size from 1 MB to 512 KB for the serial and epsilon GCs, reducing memory usage and image size in many cases.
77
* (GR-45841) BellSoft added support for the JFR event ThreadCPULoad.
88
* (GR-45994) Removed the option `-H:EnableSignalAPI`. Please use the runtime option `EnableSignalHandling` if it is necessary to enable or disable signal handling explicitly.
9+
* (GR-39406) Simulation of class initializer: Class initializer of classes that are not marked for initialization at image build time are simulated at image build time to avoid executing them at image run time.
910

1011
## Version 23.0.0
1112
* (GR-40187) Report invalid use of SVM specific classes on image class- or module-path as error. As a temporary workaround, `-H:+AllowDeprecatedBuilderClassesOnImageClasspath` allows turning the error into a warning.

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,7 +1397,11 @@ def cinterfacetutorial(args):
13971397

13981398
@mx.command(suite.name, 'clinittest', 'Runs the ')
13991399
def clinittest(args):
1400-
def build_and_test_clinittest_image(native_image, args=None):
1400+
def build_and_test_clinittest_images(native_image, args=None):
1401+
build_and_test_clinittest_image(native_image, args, True)
1402+
build_and_test_clinittest_image(native_image, args, False)
1403+
1404+
def build_and_test_clinittest_image(native_image, args, new_class_init_policy):
14011405
args = [] if args is None else args
14021406
test_cp = classpath('com.oracle.svm.test')
14031407
build_dir = join(svmbuild_dir(), 'clinittest')
@@ -1407,11 +1411,17 @@ def build_and_test_clinittest_image(native_image, args=None):
14071411
remove_tree(build_dir)
14081412
mkpath(build_dir)
14091413

1414+
if new_class_init_policy:
1415+
policy_args = ['-H:+UseNewExperimentalClassInitialization', '-H:+SimulateClassInitializer', '-H:Features=com.oracle.svm.test.clinit.TestClassInitializationFeatureNewPolicyFeature']
1416+
else:
1417+
policy_args = ['-H:-UseNewExperimentalClassInitialization', '-H:-SimulateClassInitializer', '-H:Features=com.oracle.svm.test.clinit.TestClassInitializationFeatureOldPolicyFeature']
1418+
14101419
# Build and run the example
14111420
native_image(
1412-
['-H:Path=' + build_dir, '-cp', test_cp, '-H:Class=com.oracle.svm.test.clinit.TestClassInitializationMustBeSafeEarly',
1413-
'-H:Features=com.oracle.svm.test.clinit.TestClassInitializationMustBeSafeEarlyFeature',
1414-
'-H:+PrintClassInitialization', '-H:Name=clinittest', '-H:+ReportExceptionStackTraces'] + args)
1421+
['-H:Path=' + build_dir, '-cp', test_cp, '-H:Class=com.oracle.svm.test.clinit.TestClassInitialization',
1422+
'-J--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED',
1423+
'-J-ea', '-J-esa',
1424+
'-H:+PrintClassInitialization', '-H:Name=clinittest', '-H:+ReportExceptionStackTraces'] + policy_args + args)
14151425
mx.run([join(build_dir, 'clinittest')])
14161426

14171427
# Check the reports for initialized classes
@@ -1425,9 +1435,17 @@ def checkLine(line, marker, init_kind, msg, wrongly_initialized_lines):
14251435
"Classes marked with " + marker + " must have init kind " + init_kind + " and message " + msg)]
14261436
with open(classes_file) as f:
14271437
for line in f:
1428-
checkLine(line, "MustBeDelayed", "RUN_TIME", "classes are initialized at run time by default", wrongly_initialized_lines)
1429-
checkLine(line, "MustBeSafeEarly", "BUILD_TIME", "class proven as side-effect free before analysis", wrongly_initialized_lines)
1430-
checkLine(line, "MustBeSafeLate", "BUILD_TIME", "class proven as side-effect free after analysis", wrongly_initialized_lines)
1438+
if new_class_init_policy:
1439+
checkLine(line, "MustBeSafeEarly", "SIMULATED", "classes are initialized at run time by default", wrongly_initialized_lines)
1440+
checkLine(line, "MustBeSafeLate", "SIMULATED", "classes are initialized at run time by default", wrongly_initialized_lines)
1441+
checkLine(line, "MustBeSimulated", "SIMULATED", "classes are initialized at run time by default", wrongly_initialized_lines)
1442+
checkLine(line, "MustBeDelayed", "RUN_TIME", "classes are initialized at run time by default", wrongly_initialized_lines)
1443+
else:
1444+
checkLine(line, "MustBeSafeEarly", "BUILD_TIME", "class proven as side-effect free before analysis", wrongly_initialized_lines)
1445+
checkLine(line, "MustBeSafeLate", "BUILD_TIME", "class proven as side-effect free after analysis", wrongly_initialized_lines)
1446+
checkLine(line, "MustBeSimulated", "RUN_TIME", "classes are initialized at run time by default", wrongly_initialized_lines)
1447+
checkLine(line, "MustBeDelayed", "RUN_TIME", "classes are initialized at run time by default", wrongly_initialized_lines)
1448+
14311449
if len(wrongly_initialized_lines) > 0:
14321450
msg = ""
14331451
for (line, error) in wrongly_initialized_lines:
@@ -1439,7 +1457,7 @@ def checkLine(line, marker, init_kind, msg, wrongly_initialized_lines):
14391457

14401458
check_class_initialization(all_classes_file)
14411459

1442-
native_image_context_run(build_and_test_clinittest_image, args)
1460+
native_image_context_run(build_and_test_clinittest_images, args)
14431461

14441462

14451463
class SubstrateJvmFuncsFallbacksBuilder(mx.Project):

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ protected final void scanField(AnalysisField field, JavaConstant receiver, ScanR
154154
/* The value is not available yet. */
155155
return;
156156
}
157-
JavaConstant fieldValue = bb.getConstantReflectionProvider().readFieldValue(field, receiver);
157+
JavaConstant fieldValue = bb.getUniverse().getHeapScanner().readFieldValue(field, receiver);
158158
if (fieldValue == null) {
159159
StringBuilder backtrace = new StringBuilder();
160160
buildObjectBacktrace(bb, reason, backtrace);

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapPrimitiveArray.java

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
import java.lang.reflect.Array;
2828
import java.util.function.Consumer;
2929

30-
import org.graalvm.compiler.debug.GraalError;
31-
3230
import com.oracle.graal.pointsto.ObjectScanner;
3331
import com.oracle.graal.pointsto.meta.AnalysisType;
3432
import com.oracle.graal.pointsto.util.AnalysisError;
@@ -97,35 +95,10 @@ public JavaConstant readElementValue(int idx) {
9795

9896
@Override
9997
public void setElement(int idx, JavaConstant value) {
100-
/*
101-
* Constants for sub-integer types are often just integer constants, i.e., we cannot rely on
102-
* the JavaKind of the constant to match the type of the array.
103-
*/
104-
if (array instanceof boolean[] booleanArray) {
105-
booleanArray[idx] = value.asInt() != 0;
106-
} else if (array instanceof byte[] byteArray) {
107-
byte v = (byte) value.asInt();
108-
GraalError.guarantee(v == value.asInt(), "type mismatch");
109-
byteArray[idx] = v;
110-
} else if (array instanceof short[] shortArray) {
111-
short v = (short) value.asInt();
112-
GraalError.guarantee(v == value.asInt(), "type mismatch");
113-
shortArray[idx] = v;
114-
} else if (array instanceof char[] charArray) {
115-
char v = (char) value.asInt();
116-
GraalError.guarantee(v == value.asInt(), "type mismatch");
117-
charArray[idx] = v;
118-
} else if (array instanceof int[] intArray) {
119-
intArray[idx] = value.asInt();
120-
} else if (array instanceof long[] longArray) {
121-
longArray[idx] = value.asLong();
122-
} else if (array instanceof float[] floatArray) {
123-
floatArray[idx] = value.asFloat();
124-
} else if (array instanceof double[] doubleArray) {
125-
doubleArray[idx] = value.asDouble();
126-
} else {
127-
throw AnalysisError.shouldNotReachHere("Unexpected array type: " + array.getClass());
98+
if (value.getJavaKind() != type.getComponentType().getJavaKind()) {
99+
throw AnalysisError.shouldNotReachHere("Cannot store value of kind " + value.getJavaKind() + " into primitive array of type " + type);
128100
}
101+
Array.set(array, idx, value.asBoxedPrimitive());
129102
}
130103

131104
@Override

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ void markTypeInstantiated(AnalysisType type, ScanReason reason) {
181181
universe.getBigbang().registerTypeAsInHeap(type, reason);
182182
}
183183

184-
JavaConstant createImageHeapConstant(JavaConstant constant, ScanReason reason) {
184+
public JavaConstant createImageHeapConstant(JavaConstant constant, ScanReason reason) {
185185
if (isNonNullObjectConstant(constant)) {
186186
return getOrCreateImageHeapConstant(constant, reason);
187187
}
@@ -490,6 +490,10 @@ protected ValueSupplier<JavaConstant> readHostedFieldValue(AnalysisField field,
490490
return ValueSupplier.eagerValue(value);
491491
}
492492

493+
public JavaConstant readFieldValue(AnalysisField field, JavaConstant receiver) {
494+
return constantReflection.readFieldValue(field, receiver);
495+
}
496+
493497
protected boolean skipScanning() {
494498
return false;
495499
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ public enum UsageKind {
183183
}
184184

185185
private final AnalysisFuture<Void> onTypeReachableTask;
186+
private final AnalysisFuture<Void> initializeMetaDataTask;
187+
186188
/**
187189
* Additional information that is only available for types that are marked as reachable.
188190
*/
@@ -302,6 +304,7 @@ public AnalysisType(AnalysisUniverse universe, ResolvedJavaType javaType, JavaKi
302304

303305
/* The registration task initializes the type. */
304306
this.onTypeReachableTask = new AnalysisFuture<>(() -> universe.onTypeReachable(this), null);
307+
this.initializeMetaDataTask = new AnalysisFuture<>(() -> universe.initializeMetaData(this), null);
305308
this.typeData = new AnalysisFuture<>(() -> {
306309
AnalysisError.guarantee(universe.getHeapScanner() != null, "Heap scanner is not available.");
307310
return universe.getHeapScanner().computeTypeData(this);
@@ -689,6 +692,10 @@ public void ensureOnTypeReachableTaskDone() {
689692
onTypeReachableTask.ensureDone();
690693
}
691694

695+
public AnalysisFuture<Void> getInitializeMetaDataTask() {
696+
return initializeMetaDataTask;
697+
}
698+
692699
public boolean getReachabilityListenerNotified() {
693700
return reachabilityListenerNotified;
694701
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,10 @@ public void onTypeReachable(AnalysisType type) {
702702
}
703703
}
704704

705+
public void initializeMetaData(AnalysisType type) {
706+
bb.initializeMetaData(type);
707+
}
708+
705709
public SubstitutionProcessor getSubstitutions() {
706710
return substitutions;
707711
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysisGraphDecoder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public class InlineBeforeAnalysisGraphDecoder extends PEGraphDecoder {
5959

6060
public class InlineBeforeAnalysisMethodScope extends PEMethodScope {
6161

62-
private final InlineBeforeAnalysisPolicy.AbstractPolicyScope policyScope;
62+
public final InlineBeforeAnalysisPolicy.AbstractPolicyScope policyScope;
6363

6464
private boolean inliningAborted;
6565

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@
260260
import com.oracle.svm.hosted.cenum.CEnumCallWrapperSubstitutionProcessor;
261261
import com.oracle.svm.hosted.classinitialization.ClassInitializationFeature;
262262
import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport;
263+
import com.oracle.svm.hosted.classinitialization.SimulateClassInitializerSupport;
263264
import com.oracle.svm.hosted.code.CEntryPointCallStubSupport;
264265
import com.oracle.svm.hosted.code.CEntryPointData;
265266
import com.oracle.svm.hosted.code.CFunctionSubstitutionProcessor;
@@ -909,6 +910,8 @@ protected void setupNativeImage(OptionValues options, Map<Method, CEntryPointDat
909910
originalProviders, platformConfig, classInitializationSupport, aMetaAccess);
910911
aUniverse.hostVM().initializeProviders(aProviders);
911912

913+
ImageSingletons.add(SimulateClassInitializerSupport.class, ((SVMHost) aUniverse.hostVM()).createSimulateClassInitializerSupport(aMetaAccess));
914+
912915
bb = createBigBang(options, aUniverse, aMetaAccess, aProviders, analysisExecutor, loader.watchdog::recordActivity,
913916
annotationSubstitutions);
914917
aUniverse.setBigBang(bb);

0 commit comments

Comments
 (0)