|
66 | 66 | import com.oracle.svm.core.SubstrateUtil; |
67 | 67 | import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; |
68 | 68 | import com.oracle.svm.core.feature.InternalFeature; |
| 69 | +import com.oracle.svm.core.heap.UnknownObjectField; |
69 | 70 | import com.oracle.svm.core.jdk.Resources; |
70 | 71 | import com.oracle.svm.core.jdk.RuntimeModuleSupport; |
71 | 72 | import com.oracle.svm.core.util.VMError; |
| 73 | +import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; |
72 | 74 | import com.oracle.svm.util.LogUtils; |
73 | 75 | import com.oracle.svm.util.ModuleSupport; |
74 | 76 | import com.oracle.svm.util.ReflectionUtil; |
@@ -124,17 +126,6 @@ public void duringSetup(DuringSetupAccess access) { |
124 | 126 | FeatureImpl.DuringSetupAccessImpl accessImpl = (FeatureImpl.DuringSetupAccessImpl) access; |
125 | 127 | moduleLayerFeatureUtils = new ModuleLayerFeatureUtils(accessImpl.imageClassLoader); |
126 | 128 |
|
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); |
138 | 129 | RuntimeModuleSupport.instance().setHostedToRuntimeModuleMapper(moduleLayerFeatureUtils::getOrCreateRuntimeModuleForHostedModule); |
139 | 130 |
|
140 | 131 | /* |
@@ -168,6 +159,28 @@ public void afterRegistration(AfterRegistrationAccess access) { |
168 | 159 | } |
169 | 160 | } |
170 | 161 |
|
| 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 | + |
171 | 184 | @Override |
172 | 185 | public void afterAnalysis(AfterAnalysisAccess access) { |
173 | 186 | FeatureImpl.AfterAnalysisAccessImpl accessImpl = (FeatureImpl.AfterAnalysisAccessImpl) access; |
|
0 commit comments