Skip to content

Commit a9ec779

Browse files
committed
Scan RuntimeModuleSupport.bootLayer prototype object.
1 parent 3f74e7e commit a9ec779

File tree

1 file changed

+24
-11
lines changed

1 file changed

+24
-11
lines changed

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

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@
6666
import com.oracle.svm.core.SubstrateUtil;
6767
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
6868
import com.oracle.svm.core.feature.InternalFeature;
69+
import com.oracle.svm.core.heap.UnknownObjectField;
6970
import com.oracle.svm.core.jdk.Resources;
7071
import com.oracle.svm.core.jdk.RuntimeModuleSupport;
7172
import com.oracle.svm.core.util.VMError;
73+
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
7274
import com.oracle.svm.util.LogUtils;
7375
import com.oracle.svm.util.ModuleSupport;
7476
import com.oracle.svm.util.ReflectionUtil;
@@ -124,17 +126,6 @@ public void duringSetup(DuringSetupAccess access) {
124126
FeatureImpl.DuringSetupAccessImpl accessImpl = (FeatureImpl.DuringSetupAccessImpl) access;
125127
moduleLayerFeatureUtils = new ModuleLayerFeatureUtils(accessImpl.imageClassLoader);
126128

127-
/*
128-
* Generate a temporary module layer to serve as a runtime boot module layer until the
129-
* analysis is finished.
130-
*/
131-
Set<String> baseModules = ModuleLayer.boot().modules()
132-
.stream()
133-
.map(Module::getName)
134-
.collect(Collectors.toSet());
135-
Function<String, ClassLoader> clf = moduleLayerFeatureUtils::getClassLoaderForBootLayerModule;
136-
ModuleLayer runtimeBootLayer = synthesizeRuntimeModuleLayer(new ArrayList<>(List.of(ModuleLayer.empty())), accessImpl.imageClassLoader, baseModules, Set.of(), clf, null);
137-
RuntimeModuleSupport.instance().setBootLayer(runtimeBootLayer);
138129
RuntimeModuleSupport.instance().setHostedToRuntimeModuleMapper(moduleLayerFeatureUtils::getOrCreateRuntimeModuleForHostedModule);
139130

140131
/*
@@ -168,6 +159,28 @@ public void afterRegistration(AfterRegistrationAccess access) {
168159
}
169160
}
170161

162+
@Override
163+
public void beforeAnalysis(BeforeAnalysisAccess access) {
164+
scanRuntimeBootLayerPrototype((BeforeAnalysisAccessImpl) access);
165+
}
166+
167+
/**
168+
* Generate a temporary module layer to serve as a prototype object for
169+
* {@link RuntimeModuleSupport}.bootLayer. The value doesn't need to actually be set in the
170+
* field, just scanned such that the analysis sees the deep type hierarchy. The field value
171+
* wouldn't be processed during analysis anyway since the field is annotated with
172+
* {@link UnknownObjectField}, only the field declared type is injected in the type flow graphs.
173+
* The concrete value is set in {@link ModuleLayerFeature#afterAnalysis}. Later when the field
174+
* is read the lazy value supplier scans the concrete value and patches the shadow heap.
175+
*/
176+
private void scanRuntimeBootLayerPrototype(BeforeAnalysisAccessImpl accessImpl) {
177+
Set<String> baseModules = ModuleLayer.boot().modules().stream().map(Module::getName).collect(Collectors.toSet());
178+
Function<String, ClassLoader> clf = moduleLayerFeatureUtils::getClassLoaderForBootLayerModule;
179+
ModuleLayer runtimeBootLayer = synthesizeRuntimeModuleLayer(new ArrayList<>(List.of(ModuleLayer.empty())), accessImpl.imageClassLoader, baseModules, Set.of(), clf, null);
180+
/* Only scan the value if module support is enabled and bootLayer field is reachable. */
181+
accessImpl.registerReachabilityHandler((a) -> accessImpl.rescanObject(runtimeBootLayer), ReflectionUtil.lookupField(RuntimeModuleSupport.class, "bootLayer"));
182+
}
183+
171184
@Override
172185
public void afterAnalysis(AfterAnalysisAccess access) {
173186
FeatureImpl.AfterAnalysisAccessImpl accessImpl = (FeatureImpl.AfterAnalysisAccessImpl) access;

0 commit comments

Comments
 (0)